ware_house_page.go 23 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015
  1. package Warehouse
  2. import (
  3. "context"
  4. "fmt"
  5. "log"
  6. gotime "time"
  7. "strconv"
  8. "strings"
  9. "os"
  10. "io/ioutil"
  11. "path/filepath"
  12. "encoding/json"
  13. "reflect"
  14. "database/sql"
  15. _ "github.com/mattn/go-sqlite3"
  16. "github.com/zyxar/argo/rpc"
  17. //"github.com/veandco/go-sdl2/sdl"
  18. "github.com/veandco/go-sdl2/ttf"
  19. "github.com/cuu/gogame/surface"
  20. "github.com/cuu/gogame/time"
  21. "github.com/cuu/gogame/event"
  22. "github.com/cuu/gogame/rect"
  23. "github.com/cuu/grab"
  24. "github.com/clockworkpi/LauncherGoDev/sysgo"
  25. "github.com/clockworkpi/LauncherGoDev/sysgo/UI"
  26. )
  27. type WareHouse struct {
  28. UI.Page
  29. ListFontObj15 *ttf.Font
  30. ListFontObj12 *ttf.Font
  31. Icons map[string]UI.IconItemInterface
  32. BGwidth int
  33. BGheight int
  34. DrawOnce bool
  35. Scroller *UI.ListScroller
  36. RemovePage *UI.YesCancelConfirmPage
  37. Keyboard *UI.Keyboard
  38. PreviewPage *ImageDownloadProcessPage
  39. LoadHousePage *LoadHousePage
  40. WareHouseDB string
  41. MyStack *WareHouseStack
  42. rpcc rpc.Client
  43. rpcSecret string
  44. rpcURI string
  45. Aria2DownloadingGid string // the Downloading Gid of aria2c
  46. Downloading chan bool
  47. Downloader *grab.Client
  48. resp *grab.Response
  49. req *grab.Request
  50. RefreshTicker *gotime.Ticker
  51. ScrolledCnt int
  52. }
  53. func NewWareHouse() *WareHouse {
  54. p := &WareHouse{}
  55. p.ListFontObj12 = UI.MyLangManager.TrFont("notosanscjk12")
  56. p.ListFontObj15 = UI.MyLangManager.TrFont("varela15")
  57. p.Icons = make(map[string]UI.IconItemInterface)
  58. p.FootMsg = [5]string{"Nav","Update","Up","Back","Select"}
  59. p.WareHouseDB = "foo.db"
  60. p.BGwidth = 320
  61. p.BGheight = 240-24-20
  62. p.MyStack = NewWareHouseStack()
  63. repo := make(map[string]string)
  64. repo["title"] = "github.com/clockworkpi/warehouse"
  65. repo["file"] = "https://raw.githubusercontent.com/clockworkpi/warehouse/master/index.json"
  66. repo["type"] = "source"
  67. p.MyStack.Push(repo)
  68. p.rpcURI = sysgo.Aria2Url
  69. return p
  70. }
  71. func (self *WareHouse) GetAria2DownloadingPercent(url string) int {
  72. if resp,err := self.rpcc.TellActive();err == nil {
  73. for _,v := range resp {
  74. if uris,err := self.rpcc.GetURIs(v.Gid); err == nil {
  75. for _,x := range uris {
  76. if x.URI == url {
  77. comp_len,_ := strconv.ParseInt(v.CompletedLength,10,64)
  78. totl_len,_ := strconv.ParseInt(v.TotalLength,10,64)
  79. pct := float64(comp_len)/float64(totl_len)
  80. pct = pct * 100.0
  81. return int(pct)
  82. }
  83. }
  84. }
  85. }
  86. }
  87. return -1;///None
  88. }
  89. func (self *WareHouse) UpdateProcessInterval(ms int) {
  90. dirty := false
  91. L:
  92. for {
  93. select {
  94. case <- self.RefreshTicker.C:
  95. for _,i := range self.MyList {
  96. x := i.(*WareHouseListItem)
  97. if x.Type == "launcher" || x.Type == "pico8" || x.Type == "tic80" {
  98. percent := self.GetAria2DownloadingPercent(x.Value["file"])
  99. if percent < 0 {
  100. x.SetSmallText("")
  101. }else {
  102. x.SetSmallText(fmt.Sprintf("%d%%",percent))
  103. dirty = true
  104. }
  105. }
  106. }
  107. if self.Screen.CurPage() == self && dirty == true {
  108. self.Screen.Draw()
  109. self.Screen.SwapAndShow()
  110. }
  111. dirty = false
  112. case v:= <- self.Downloading:
  113. if v== false {
  114. break L
  115. }
  116. }
  117. }
  118. }
  119. func (self *WareHouse) SyncWareHouse() []map[string]string {
  120. db, err := sql.Open("sqlite3", self.WareHouseDB)
  121. if err != nil {
  122. log.Fatal(err)
  123. return nil
  124. }
  125. defer db.Close()
  126. //id,title,file,type
  127. rows, err := db.Query("select * from warehouse")
  128. if err != nil {
  129. log.Fatal(err)
  130. }
  131. defer rows.Close()
  132. var ret []map[string]string
  133. for rows.Next() {
  134. var id int
  135. var title string
  136. var file string
  137. var type_ string
  138. err = rows.Scan(&id, &title,&file,&type_)
  139. if err != nil {
  140. log.Fatal(err)
  141. }
  142. w_dbt := make(map[string]string)
  143. w_dbt["title"] = title
  144. w_dbt["file"] = file
  145. w_dbt["type"] = type_
  146. ret = append(ret,w_dbt)
  147. }
  148. return ret
  149. }
  150. func (self *WareHouse) SyncTasks() []map[string]string {
  151. db, err := sql.Open("sqlite3", self.WareHouseDB)
  152. if err != nil {
  153. log.Fatal(err)
  154. return nil
  155. }
  156. defer db.Close()
  157. //id,gid,title,file,type,status,totalLength,completedLength,fav
  158. rows, err := db.Query("select * from tasks")
  159. if err != nil {
  160. log.Fatal(err)
  161. }
  162. defer rows.Close()
  163. var ret []map[string]string
  164. for rows.Next() {
  165. var id int
  166. var gid string
  167. var title string
  168. var file string
  169. var type_ string
  170. var status string
  171. var totalLength string
  172. var completedLength string
  173. var fav string
  174. err = rows.Scan(&id,&gid, &title,&file,&type_,&status,&totalLength,&completedLength,&fav)
  175. if err != nil {
  176. log.Fatal(err)
  177. }
  178. w_dbt := make(map[string]string)
  179. w_dbt["gid"] = gid
  180. w_dbt["title"] = title
  181. w_dbt["file"] = file
  182. w_dbt["type"] = type_
  183. w_dbt["status"] = status
  184. w_dbt["totalLength"] = totalLength
  185. w_dbt["completedLength"] = completedLength
  186. ret = append(ret,w_dbt)
  187. }
  188. return ret
  189. }
  190. func IsSlice(v interface{}) bool {
  191. if reflect.TypeOf(v).Kind() == reflect.Slice || reflect.TypeOf(v).Kind() == reflect.Array {
  192. return true
  193. }
  194. return false
  195. }
  196. func (self *WareHouse) SyncList() {
  197. self.MyList = self.MyList[:0]
  198. start_x := 0
  199. start_y := 0
  200. last_height := 0
  201. var repos []map[string]string
  202. fmt.Printf("SyncList: %+v\n", self.MyStack)
  203. stk := self.MyStack.Last()
  204. stk_len := self.MyStack.Length()
  205. if IsSlice(stk) {
  206. repos = append(repos, stk.([]map[string]string)...)
  207. }else {
  208. repos = append(repos, stk.(map[string]string))
  209. }
  210. add_new_house := make(map[string]string)
  211. add_new_house["title"] = "Add new warehouse..."
  212. add_new_house["file"] = "master/index.json"
  213. add_new_house["type"] = "add_house"
  214. add_new_house["status"] = "complete"
  215. if stk_len == 1 {//on top
  216. ware_menu := self.SyncWareHouse()
  217. if len(ware_menu) > 0 {
  218. repos = append(repos,ware_menu...)
  219. }
  220. tasks_menu := self.SyncTasks()
  221. if len(tasks_menu) > 0 {
  222. repos = append(repos,tasks_menu...)
  223. }
  224. repos = append(repos,add_new_house)
  225. }
  226. for _, u := range repos {
  227. fmt.Printf("%+v\n",u)
  228. li := NewWareHouseListItem()
  229. li.Parent = self
  230. li.PosX = start_x
  231. li.PosY = start_y + last_height
  232. li.Width = UI.Width
  233. li.Fonts["normal"] = self.ListFontObj15
  234. li.Fonts["small"] = self.ListFontObj12
  235. li.ReadOnly = true
  236. li.Type = u["type"]
  237. li.Value = u
  238. li.Init(u["title"])
  239. if stk_len > 1 {
  240. remote_file_url := u["file"]
  241. menu_file := strings.Split(remote_file_url,"raw.githubusercontent.com")[1]
  242. home_path, err := os.UserHomeDir()
  243. if err != nil {
  244. log.Fatal( err )
  245. }
  246. local_menu_file := fmt.Sprintf(aria2dl_folder,home_path,menu_file)
  247. fmt.Println("for loop ",local_menu_file)
  248. if UI.FileExists(local_menu_file) {
  249. li.ReadOnly = false
  250. }else {
  251. li.ReadOnly = true
  252. }
  253. } else if stk_len == 1 {
  254. if _,ok := u["status"];ok {
  255. if u["status"] == "complete" {
  256. li.ReadOnly = false
  257. }
  258. }
  259. if u["type"] == "source" {
  260. li.ReadOnly = false
  261. }
  262. }
  263. last_height += li.Height
  264. if li.Type == "launcher" || li.Type == "pico8" || li.Type == "tic80" {
  265. li.SetSmallText("")
  266. }
  267. self.MyList = append(self.MyList,li)
  268. }
  269. self.RefreshPsIndex()
  270. }
  271. func (self *WareHouse) Init() {
  272. if self.Screen != nil {
  273. if self.Screen.CanvasHWND != nil && self.CanvasHWND == nil {
  274. self.HWND = self.Screen.CanvasHWND
  275. self.CanvasHWND = surface.Surface(self.Screen.Width, self.BGheight)
  276. }
  277. self.PosX = self.Index * self.Screen.Width
  278. self.Width = self.Screen.Width //equal to screen width
  279. self.Height = self.Screen.Height
  280. done := UI.NewIconItem()
  281. done.ImgSurf = UI.MyIconPool.GetImgSurf("done")
  282. done.MyType = UI.ICON_TYPES["STAT"]
  283. done.Parent = self
  284. self.Icons["done"] = done
  285. ps := UI.NewInfoPageSelector()
  286. ps.Parent = self
  287. self.Ps = ps
  288. self.PsIndex = 0
  289. self.Scroller = UI.NewListScroller()
  290. self.Scroller.Parent = self
  291. self.Scroller.PosX = self.Width - 10
  292. self.Scroller.PosY = 2
  293. self.Scroller.Init()
  294. self.Scroller.SetCanvasHWND(self.CanvasHWND)
  295. self.RemovePage = UI.NewYesCancelConfirmPage()
  296. self.RemovePage.Screen = self.Screen
  297. self.RemovePage.StartOrAEvent = self.RemoveGame
  298. self.RemovePage.Name = "Are you sure?"
  299. self.RemovePage.Init()
  300. self.Keyboard = UI.NewKeyboard()
  301. self.Keyboard.Name = "Enter warehouse addr"
  302. self.Keyboard.FootMsg = [5]string{"Nav.","Add","ABC","Backspace","Enter"}
  303. self.Keyboard.Screen = self.Screen
  304. self.Keyboard.Init()
  305. self.Keyboard.SetPassword("github.com/clockworkpi/warehouse")
  306. self.Keyboard.Caller = self
  307. self.PreviewPage = NewImageDownloadProcessPage()
  308. self.PreviewPage.Screen = self.Screen
  309. self.PreviewPage.Name ="Preview"
  310. self.PreviewPage.Init()
  311. self.LoadHousePage = NewLoadHousePage()
  312. self.LoadHousePage.Screen = self.Screen
  313. self.LoadHousePage.Name = "Warehouse"
  314. self.LoadHousePage.Parent = self
  315. self.LoadHousePage.Init()
  316. rpcc, err := rpc.New(context.Background(),
  317. self.rpcURI,
  318. self.rpcSecret,
  319. gotime.Second, AppNotifier{Parent:self})
  320. if err != nil {
  321. fmt.Fprintln(os.Stderr, err)
  322. os.Exit(2)
  323. }
  324. self.rpcc = rpcc
  325. self.Downloader = grab.NewClient()
  326. self.Downloading = make(chan bool,1)
  327. self.RefreshTicker = gotime.NewTicker(500 * gotime.Millisecond)
  328. //self.RefreshTicker.Stop()
  329. self.SetDownloading(true)
  330. go self.UpdateProcessInterval(500)
  331. }
  332. }
  333. func (self *WareHouse) SetDownloading(v bool) {
  334. for len(self.Downloading) > 0 {
  335. <- self.Downloading
  336. }
  337. self.Downloading <- v
  338. }
  339. func (self *WareHouse) ResetHouse() {
  340. if self.PsIndex > len(self.MyList) -1 {
  341. return
  342. }
  343. cur_li := self.MyList[self.PsIndex].(*WareHouseListItem)
  344. home_path, _ := os.UserHomeDir()
  345. if cur_li.Value["type"] == "source" {
  346. remote_file_url := cur_li.Value["file"]
  347. parts := strings.Split(remote_file_url,"raw.githubusercontent.com")
  348. menu_file := parts[1]
  349. local_menu_file := fmt.Sprintf(aria2dl_folder,home_path,menu_file)
  350. local_menu_file_path := filepath.Dir(local_menu_file)
  351. fmt.Println(local_menu_file)
  352. local_jsons,err := filepath.Glob(local_menu_file_path+"/**/*.json")
  353. if err != nil {
  354. fmt.Println(err)
  355. }
  356. if UI.FileExists(local_menu_file) {
  357. os.Remove(local_menu_file)
  358. }
  359. if UI.FileExists(local_menu_file+".aria2") {
  360. os.Remove(local_menu_file+".aria2")
  361. }
  362. for _,x := range local_jsons {
  363. os.Remove(x)
  364. }
  365. self.Screen.MsgBox.SetText("Done")
  366. self.Screen.MsgBox.Draw()
  367. self.Screen.SwapAndShow()
  368. }
  369. }
  370. func (self *WareHouse) LoadHouse() {
  371. if self.PsIndex > len(self.MyList) -1 {
  372. return
  373. }
  374. cur_li := self.MyList[self.PsIndex].(*WareHouseListItem)
  375. if cur_li.Value["type"] == "source" || cur_li.Value["type"] == "dir" {
  376. self.LoadHousePage.URL = cur_li.Value["file"]
  377. self.Screen.PushPage(self.LoadHousePage)
  378. self.Screen.Draw()
  379. self.Screen.SwapAndShow()
  380. }
  381. }
  382. func (self *WareHouse) PreviewGame() {
  383. if self.PsIndex > len(self.MyList) -1 {
  384. return
  385. }
  386. cur_li := self.MyList[self.PsIndex].(*WareHouseListItem)
  387. if cur_li.Value["type"] == "launcher" ||
  388. cur_li.Value["type"] == "pico8" ||
  389. cur_li.Value["type"] == "tic80" {
  390. if _,ok := cur_li.Value["shots"];ok {
  391. fmt.Println(cur_li.Value["shots"])
  392. self.PreviewPage.URL = cur_li.Value["shots"]
  393. self.Screen.PushPage(self.PreviewPage)
  394. self.Screen.Draw()
  395. self.Screen.SwapAndShow()
  396. }
  397. }
  398. }
  399. //check if an Url is downloading in aria2c
  400. func (self *WareHouse) UrlIsDownloading(url string) (string,bool) {
  401. if resp,err := self.rpcc.TellActive();err == nil {
  402. for _,v := range resp {
  403. if uris,err := self.rpcc.GetURIs(v.Gid);err == nil {
  404. for _,x := range uris {
  405. if x.URI == url {
  406. fmt.Println(x.URI," ",url)
  407. return v.Gid,true
  408. }
  409. }
  410. }
  411. }
  412. }else {
  413. log.Fatal(err)
  414. }
  415. return "",false
  416. }
  417. func (self *WareHouse) RemoveGame() {
  418. if self.PsIndex > len(self.MyList) -1 {
  419. return
  420. }
  421. fmt.Println("RemoveGame")
  422. cur_li := self.MyList[self.PsIndex].(*WareHouseListItem)
  423. fmt.Println("Remove cur_li._Value",cur_li.Value)
  424. home_path, _ := os.UserHomeDir()
  425. if cur_li.Value["type"] == "source" {
  426. db, err := sql.Open("sqlite3", self.WareHouseDB)
  427. if err != nil {
  428. log.Fatal(err)
  429. }
  430. defer db.Close()
  431. _, err = db.Exec(fmt.Sprintf("DELETE FROM warehouse WHERE file = '%s'",
  432. cur_li.Value["file"]))
  433. if err != nil {
  434. log.Fatal(err)
  435. }
  436. } else if cur_li.Value["type"] == "launcher" ||
  437. cur_li.Value["type"] == "pico8" ||
  438. cur_li.Value["type"] == "tic80" {
  439. remote_file_url := cur_li.Value["file"]
  440. parts := strings.Split(remote_file_url,"raw.githubusercontent.com")
  441. menu_file := parts[1]
  442. local_menu_file := fmt.Sprintf(aria2dl_folder,home_path,menu_file)
  443. local_menu_file_path := filepath.Dir(local_menu_file)
  444. gid,ret := self.UrlIsDownloading(remote_file_url)
  445. if ret == true {
  446. self.rpcc.Remove(gid)
  447. }
  448. if UI.FileExists(local_menu_file) {
  449. os.Remove(local_menu_file)
  450. }
  451. if UI.FileExists(local_menu_file+".aria2") {
  452. os.Remove(local_menu_file+".aria2")
  453. }
  454. if UI.FileExists(filepath.Join(local_menu_file_path,cur_li.Value["title"])) {
  455. os.RemoveAll(filepath.Join(local_menu_file_path,cur_li.Value["title"]))
  456. }
  457. }
  458. }
  459. func (self *WareHouse) Click() {
  460. if self.PsIndex > len(self.MyList) -1 {
  461. return
  462. }
  463. cur_li := self.MyList[self.PsIndex].(*WareHouseListItem)
  464. home_path, _ := os.UserHomeDir()
  465. fmt.Println("Click cur_li._Value",cur_li.Value)
  466. if cur_li.Value["type"] == "source" || cur_li.Value["type"] == "dir" {
  467. remote_file_url := cur_li.Value["file"]
  468. parts := strings.Split(remote_file_url,"raw.githubusercontent.com")//assume master branch
  469. menu_file := parts[1]
  470. local_menu_file := fmt.Sprintf(aria2dl_folder,home_path,menu_file)
  471. fmt.Println("warehouse click: ",local_menu_file)
  472. if UI.FileExists(local_menu_file) == false {
  473. self.LoadHouse()
  474. }else {
  475. //read the local_menu_file,push into stack,display menu
  476. self.Aria2DownloadingGid = ""
  477. var result WareHouseIndex
  478. jsonFile, err := os.Open(local_menu_file)
  479. if err != nil {
  480. fmt.Println(err)
  481. self.Screen.MsgBox.SetText("Open House failed")
  482. self.Screen.MsgBox.Draw()
  483. self.Screen.SwapAndShow()
  484. }else {
  485. defer jsonFile.Close()
  486. byteValue, _ := ioutil.ReadAll(jsonFile)
  487. json.Unmarshal(byteValue, &result)
  488. self.MyStack.Push(result.List)
  489. self.SyncList()
  490. self.Screen.Draw()
  491. self.Screen.SwapAndShow()
  492. }
  493. }
  494. } else if cur_li.Value["type"] == "add_house" {
  495. fmt.Println("show keyboard to add warehouse")
  496. self.Screen.PushCurPage()
  497. self.Screen.SetCurPage(self.Keyboard)
  498. } else {
  499. //download the game probably
  500. remote_file_url := cur_li.Value["file"]
  501. parts := strings.Split(remote_file_url,"raw.githubusercontent.com")//assume master branch
  502. menu_file := parts[1]
  503. local_menu_file := fmt.Sprintf(aria2dl_folder,home_path,menu_file)
  504. fmt.Println("Click on game ", local_menu_file)
  505. if UI.FileExists(local_menu_file) == false {
  506. gid,ret := self.UrlIsDownloading(remote_file_url)
  507. if ret == false {
  508. outfile := struct {
  509. Out string `json:"out"`
  510. }{Out:menu_file}
  511. gid,err := self.rpcc.AddURI([]string{remote_file_url},outfile)
  512. if err != nil {
  513. log.Fatal(err)
  514. }else {
  515. fmt.Println("Warehouse Click game is downloading, ",gid)
  516. fmt.Println(remote_file_url)
  517. self.Aria2DownloadingGid = gid
  518. }
  519. } else {
  520. fmt.Println(self.rpcc.TellStatus(gid,"status","totalLength","completedLength"))
  521. self.Screen.MsgBox.SetText("Getting the game now")
  522. self.Screen.MsgBox.Draw()
  523. self.Screen.SwapAndShow()
  524. time.BlockDelay(800)
  525. self.Screen.TitleBar.Redraw()
  526. }
  527. }else {
  528. fmt.Println("file downloaded ", cur_li.Value) //maybe check it if is installed fst,then execute it
  529. if cur_li.Value["type"] == "launcher" && cur_li.ReadOnly == false {
  530. local_menu_file_path := filepath.Dir(local_menu_file)
  531. game_sh := filepath.Join(local_menu_file_path,cur_li.Value["title"],cur_li.Value["title"]+".sh")
  532. fmt.Println("run game: ",game_sh, UI.FileExists(game_sh))
  533. self.Screen.RunEXE(game_sh)
  534. }
  535. if cur_li.Value["type"] == "pico8" && cur_li.ReadOnly == false {
  536. if UI.FileExists("/home/cpi/games/PICO-8/pico-8/pico8") {
  537. game_sh := "/home/cpi/launcher/Menu/GameShell/50_PICO-8/PICO-8.sh"
  538. self.Screen.RunEXE(game_sh) //pico8 manages its games self
  539. }
  540. }
  541. if cur_li.Value["type"] == "tic80" && cur_li.ReadOnly == false {
  542. game_sh := "/home/cpi/apps/Menu/51_TIC-80/TIC-80.sh"
  543. self.Screen.RunEXE(game_sh)
  544. }
  545. }
  546. }
  547. }
  548. func (self *WareHouse) OnAria2CompleteCb(gid string) {
  549. fmt.Println("OnAria2CompleteCb", gid)
  550. self.SyncList()
  551. self.Screen.Draw()
  552. self.Screen.SwapAndShow()
  553. if gid == self.Aria2DownloadingGid {
  554. self.Aria2DownloadingGid = ""
  555. }
  556. }
  557. func (self *WareHouse) raw_github_com(url string) (bool,string) {
  558. if strings.HasPrefix(url,"github.com") == false {
  559. return false,""
  560. }
  561. parts := strings.Split(url,"/")
  562. if len(parts) != 3 {
  563. return false, ""
  564. }
  565. str := []string{"https://raw.githubusercontent.com",
  566. parts[1],
  567. parts[2],
  568. "master/index.json"}
  569. return true,strings.Join(str,"/")
  570. }
  571. func (self *WareHouse) OnKbdReturnBackCb() {
  572. inputed:= strings.Join(self.Keyboard.Textarea.MyWords,"")
  573. inputed = strings.Replace(inputed,"http://","",-1)
  574. inputed = strings.Replace(inputed,"https://","",-1)
  575. if strings.HasSuffix(inputed,".git") {
  576. inputed = inputed[:len(inputed)-4]
  577. }
  578. if strings.HasSuffix(inputed,"/") {
  579. inputed = inputed[:len(inputed)-1]
  580. }
  581. fmt.Println("last: ",inputed)
  582. db, err := sql.Open("sqlite3", self.WareHouseDB)
  583. if err != nil {
  584. log.Fatal(err)
  585. return
  586. }
  587. defer db.Close()
  588. stmt, err := db.Prepare("SELECT count(*) FROM warehouse WHERE title= ?")
  589. if err != nil {
  590. log.Fatal(err)
  591. }
  592. defer stmt.Close()
  593. var cnt_str string
  594. cnt := 0
  595. err = stmt.QueryRow(inputed).Scan(&cnt_str)
  596. if err != nil {
  597. log.Fatal(err)
  598. }else {
  599. cnt,_= strconv.Atoi(cnt_str)
  600. }
  601. if cnt > 0 {
  602. self.Screen.MsgBox.SetText("Warehouse existed")
  603. self.Screen.MsgBox.Draw()
  604. self.Screen.SwapAndShow()
  605. } else {
  606. if strings.Contains(inputed,"github.com/clockworkpi/warehouse") {
  607. self.Screen.MsgBox.SetText("Warehouse existed")
  608. self.Screen.MsgBox.Draw()
  609. self.Screen.SwapAndShow()
  610. }else {
  611. valid_,_url := self.raw_github_com(inputed)
  612. if valid_ == false {
  613. self.Screen.MsgBox.SetText("Warehouse url error!")
  614. self.Screen.MsgBox.Draw()
  615. self.Screen.SwapAndShow()
  616. } else {
  617. sql_insert := fmt.Sprintf("INSERT INTO warehouse(title,file,type) VALUES('%s','%s','source');",
  618. inputed,_url)
  619. _, err = db.Exec(sql_insert)
  620. if err != nil {
  621. log.Fatal(err)
  622. }
  623. self.SyncList()
  624. self.Screen.Draw()
  625. self.Screen.SwapAndShow()
  626. }
  627. }
  628. }
  629. }
  630. func (self *WareHouse) OnExitCb() {
  631. if self.RefreshTicker != nil {
  632. self.RefreshTicker.Stop()
  633. }
  634. self.SetDownloading(false)
  635. self.rpcc.Close()
  636. }
  637. func (self *WareHouse) OnLoadCb() {
  638. if self.MyStack.Length() == 1 {
  639. self.FootMsg[2] = "Remove"
  640. self.FootMsg[1] = "Update"
  641. }else {
  642. self.FootMsg[2] = "Remove"
  643. self.FootMsg[1] = "Preview"
  644. }
  645. self.RefreshTicker = gotime.NewTicker(500 * gotime.Millisecond)
  646. self.SyncList()
  647. }
  648. func (self *WareHouse) OnReturnBackCb() {
  649. if self.MyStack.Length() == 1 {
  650. self.FootMsg[2] = "Remove"
  651. self.FootMsg[1] = "Update"
  652. }else {
  653. self.FootMsg[2] = "Remove"
  654. self.FootMsg[1] = "Preview"
  655. }
  656. self.SyncList()
  657. self.RestoreScrolled()
  658. self.Screen.Draw()
  659. self.Screen.SwapAndShow()
  660. }
  661. func (self *WareHouse) ScrollDown() {
  662. if len(self.MyList) == 0 {
  663. return
  664. }
  665. self.PsIndex += 1
  666. if self.PsIndex >= len(self.MyList) {
  667. self.PsIndex = len(self.MyList) - 1
  668. }
  669. cur_li := self.MyList[self.PsIndex]
  670. x, y := cur_li.Coord()
  671. _, h := cur_li.Size()
  672. if y+h > self.Height {
  673. for i, _ := range self.MyList {
  674. x, y = self.MyList[i].Coord()
  675. _, h = self.MyList[i].Size()
  676. self.MyList[i].NewCoord(x, y-h)
  677. }
  678. self.ScrolledCnt -= h
  679. }
  680. }
  681. func (self *WareHouse) ScrollUp() {
  682. if len(self.MyList) == 0 {
  683. return
  684. }
  685. self.PsIndex -= 1
  686. if self.PsIndex < 0 {
  687. self.PsIndex = 0
  688. }
  689. cur_li := self.MyList[self.PsIndex]
  690. x, y := cur_li.Coord()
  691. _, h := cur_li.Size()
  692. if y < 0 {
  693. for i, _ := range self.MyList {
  694. x, y = self.MyList[i].Coord()
  695. _, h = self.MyList[i].Size()
  696. self.MyList[i].NewCoord(x, y+h)
  697. }
  698. self.ScrolledCnt += h
  699. }
  700. }
  701. func (self *WareHouse) RestoreScrolled() {
  702. for i,_ := range self.MyList {
  703. x,y := self.MyList[i].Coord()
  704. self.MyList[i].NewCoord(x, y+ self.ScrolledCnt)
  705. }
  706. }
  707. func (self *WareHouse) KeyDown(ev *event.Event) {
  708. if UI.IsKeyMenuOrB(ev.Data["Key"]) {
  709. if self.MyStack.Length() > 1 {
  710. self.MyStack.Pop()
  711. if self.MyStack.Length() == 1 {
  712. self.FootMsg[2] = "Remove"
  713. self.FootMsg[1] = "Update"
  714. }else {
  715. self.FootMsg[2] = "Remove"
  716. self.FootMsg[1] = "Preview"
  717. if self.MyStack.Length() == 2 {
  718. self.FootMsg[2] = ""
  719. self.FootMsg[1] = ""
  720. }
  721. }
  722. self.SyncList()
  723. self.Screen.Draw()
  724. self.Screen.SwapAndShow()
  725. }else if self.MyStack.Length() == 1 {
  726. self.ReturnToUpLevelPage()
  727. self.Screen.Draw()
  728. self.Screen.SwapAndShow()
  729. self.RefreshTicker.Stop()
  730. }
  731. }
  732. if UI.IsKeyStartOrA(ev.Data["Key"]) {
  733. self.Click()
  734. if self.MyStack.Length() == 1 {
  735. self.FootMsg[2] = "Remove"
  736. self.FootMsg[1] = "Update"
  737. }else {
  738. self.FootMsg[2] = "Remove"
  739. self.FootMsg[1] = "Preview"
  740. if self.MyStack.Length() == 2 {
  741. self.FootMsg[2] = ""
  742. self.FootMsg[1] = ""
  743. }
  744. }
  745. self.Screen.Draw()
  746. self.Screen.SwapAndShow()
  747. }
  748. if ev.Data["Key"] == UI.CurKeys["X"] {
  749. if self.PsIndex <= len(self.MyList) -1 {
  750. cur_li := self.MyList[self.PsIndex].(*WareHouseListItem)
  751. if cur_li.Type != "dir" {
  752. if self.MyStack.Length() ==1 && self.PsIndex == 0 {
  753. //pass
  754. }else {
  755. self.Screen.PushPage(self.RemovePage)
  756. self.RemovePage.StartOrAEvent = self.RemoveGame
  757. self.Screen.Draw()
  758. self.Screen.SwapAndShow()
  759. }
  760. }
  761. return
  762. }
  763. self.SyncList()
  764. self.Screen.Draw()
  765. self.Screen.SwapAndShow()
  766. }
  767. if ev.Data["Key"] == UI.CurKeys["Y"] {
  768. if self.MyStack.Length() == 1 {
  769. self.ResetHouse()
  770. }else {
  771. self.PreviewGame()
  772. }
  773. }
  774. if ev.Data["Key"] == UI.CurKeys["Up"] {
  775. self.ScrollUp()
  776. self.Screen.Draw()
  777. self.Screen.SwapAndShow()
  778. }
  779. if ev.Data["Key"] == UI.CurKeys["Down"] {
  780. self.ScrollDown()
  781. self.Screen.Draw()
  782. self.Screen.SwapAndShow()
  783. }
  784. }
  785. func (self *WareHouse) Draw() {
  786. self.ClearCanvas()
  787. if self.PsIndex > len(self.MyList) -1 {
  788. self.PsIndex = len(self.MyList) -1
  789. }
  790. if self.PsIndex < 0 {
  791. self.PsIndex = 0
  792. }
  793. if len(self.MyList) == 0 {
  794. return
  795. } else {
  796. if len(self.MyList) * UI.DefaultInfoPageListItemHeight > self.Height {
  797. _,h := self.Ps.Size()
  798. self.Ps.NewSize(self.Width - 11,h)
  799. self.Ps.Draw()
  800. for _,v := range self.MyList {
  801. _,y := v.Coord()
  802. if y > (self.Height + self.Height/2) {
  803. break
  804. }
  805. if y < 0 {
  806. continue
  807. }
  808. v.Draw()
  809. }
  810. self.Scroller.UpdateSize(len(self.MyList)*UI.DefaultInfoPageListItemHeight,self.PsIndex*UI.DefaultInfoPageListItemHeight)
  811. self.Scroller.Draw()
  812. }else {
  813. _,h := self.Ps.Size()
  814. self.Ps.NewSize(self.Width,h)
  815. self.Ps.Draw()
  816. for _,v := range self.MyList {
  817. _,y := v.Coord()
  818. if y > self.Height + self.Height/2 {
  819. break
  820. }
  821. if y < 0 {
  822. continue
  823. }
  824. v.Draw()
  825. }
  826. }
  827. }
  828. if self.HWND != nil {
  829. surface.Fill(self.HWND, UI.MySkinManager.GiveColor("White"))
  830. rect_ := rect.Rect(self.PosX, self.PosY, self.Width, self.Height)
  831. surface.Blit(self.HWND, self.CanvasHWND, &rect_, nil)
  832. }
  833. }