ware_house_page.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998
  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. ScrolledCnt int
  51. }
  52. func NewWareHouse() *WareHouse {
  53. p := &WareHouse{}
  54. p.ListFontObj12 = UI.MyLangManager.TrFont("notosanscjk12")
  55. p.ListFontObj15 = UI.MyLangManager.TrFont("varela15")
  56. p.Icons = make(map[string]UI.IconItemInterface)
  57. p.FootMsg = [5]string{"Nav","Update","Up","Back","Select"}
  58. p.WareHouseDB = sysgo.SQLDB
  59. p.BGwidth = 320
  60. p.BGheight = 240-24-20
  61. p.MyStack = NewWareHouseStack()
  62. repo := make(map[string]string)
  63. repo["title"] = "github.com/clockworkpi/warehouse"
  64. repo["file"] = "https://raw.githubusercontent.com/clockworkpi/warehouse/master/index.json"
  65. repo["type"] = "source"
  66. p.MyStack.Push(repo)
  67. p.rpcURI = sysgo.Aria2Url
  68. return p
  69. }
  70. func (self *WareHouse) GetAria2DownloadingPercent(url string) int {
  71. if resp,err := self.rpcc.TellActive();err == nil {
  72. for _,v := range resp {
  73. if uris,err := self.rpcc.GetURIs(v.Gid); err == nil {
  74. for _,x := range uris {
  75. if x.URI == url {
  76. comp_len,_ := strconv.ParseInt(v.CompletedLength,10,64)
  77. totl_len,_ := strconv.ParseInt(v.TotalLength,10,64)
  78. pct := float64(comp_len)/float64(totl_len)
  79. pct = pct * 100.0
  80. return int(pct)
  81. }
  82. }
  83. }
  84. }
  85. }
  86. return -1;///None
  87. }
  88. func (self *WareHouse) UpdateProcessInterval(ms int) {
  89. dirty := false
  90. RefreshTicker := gotime.NewTicker(gotime.Duration(ms)*gotime.Millisecond)
  91. defer RefreshTicker.Stop()
  92. L:
  93. for {
  94. select {
  95. case <- RefreshTicker.C:
  96. for _,i := range self.MyList {
  97. x := i.(*WareHouseListItem)
  98. if x.Type == "launcher" || x.Type == "pico8" || x.Type == "tic80" {
  99. percent := self.GetAria2DownloadingPercent(x.Value["file"])
  100. if percent < 0 {
  101. x.SetSmallText("")
  102. }else {
  103. x.SetSmallText(fmt.Sprintf("%d%%",percent))
  104. dirty = true
  105. }
  106. }
  107. }
  108. if self.Screen.CurPage() == self && dirty == true {
  109. self.Screen.Refresh()
  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.Screen.HookExitCb(self)
  328. }
  329. }
  330. func (self *WareHouse) SetDownloading(v bool) {
  331. for len(self.Downloading) > 0 {
  332. <- self.Downloading
  333. }
  334. self.Downloading <- v
  335. }
  336. func (self *WareHouse) ResetHouse() {
  337. if self.PsIndex > len(self.MyList) -1 {
  338. return
  339. }
  340. cur_li := self.MyList[self.PsIndex].(*WareHouseListItem)
  341. home_path, _ := os.UserHomeDir()
  342. if cur_li.Value["type"] == "source" {
  343. remote_file_url := cur_li.Value["file"]
  344. parts := strings.Split(remote_file_url,"raw.githubusercontent.com")
  345. menu_file := parts[1]
  346. local_menu_file := fmt.Sprintf(aria2dl_folder,home_path,menu_file)
  347. local_menu_file_path := filepath.Dir(local_menu_file)
  348. fmt.Println(local_menu_file)
  349. local_jsons,err := filepath.Glob(local_menu_file_path+"/**/*.json")
  350. if err != nil {
  351. fmt.Println(err)
  352. }
  353. if UI.FileExists(local_menu_file) {
  354. os.Remove(local_menu_file)
  355. }
  356. if UI.FileExists(local_menu_file+".aria2") {
  357. os.Remove(local_menu_file+".aria2")
  358. }
  359. for _,x := range local_jsons {
  360. os.Remove(x)
  361. }
  362. self.Screen.MsgBox.SetText("Done")
  363. self.Screen.MsgBox.Draw()
  364. self.Screen.SwapAndShow()
  365. }
  366. }
  367. func (self *WareHouse) LoadHouse() {
  368. if self.PsIndex > len(self.MyList) -1 {
  369. return
  370. }
  371. cur_li := self.MyList[self.PsIndex].(*WareHouseListItem)
  372. if cur_li.Value["type"] == "source" || cur_li.Value["type"] == "dir" {
  373. self.LoadHousePage.URL = cur_li.Value["file"]
  374. self.Screen.PushPage(self.LoadHousePage)
  375. self.Screen.Refresh()
  376. }
  377. }
  378. func (self *WareHouse) PreviewGame() {
  379. if self.PsIndex > len(self.MyList) -1 {
  380. return
  381. }
  382. cur_li := self.MyList[self.PsIndex].(*WareHouseListItem)
  383. if cur_li.Value["type"] == "launcher" ||
  384. cur_li.Value["type"] == "pico8" ||
  385. cur_li.Value["type"] == "tic80" {
  386. if _,ok := cur_li.Value["shots"];ok {
  387. fmt.Println(cur_li.Value["shots"])
  388. self.PreviewPage.URL = cur_li.Value["shots"]
  389. self.Screen.PushPage(self.PreviewPage)
  390. self.Screen.Refresh()
  391. }
  392. }
  393. }
  394. //check if an Url is downloading in aria2c
  395. func (self *WareHouse) UrlIsDownloading(url string) (string,bool) {
  396. if resp,err := self.rpcc.TellActive();err == nil {
  397. for _,v := range resp {
  398. if uris,err := self.rpcc.GetURIs(v.Gid);err == nil {
  399. for _,x := range uris {
  400. if x.URI == url {
  401. fmt.Println(x.URI," ",url)
  402. return v.Gid,true
  403. }
  404. }
  405. }
  406. }
  407. }else {
  408. log.Println(err)
  409. }
  410. return "",false
  411. }
  412. func (self *WareHouse) RemoveGame() {
  413. if self.PsIndex > len(self.MyList) -1 {
  414. return
  415. }
  416. fmt.Println("RemoveGame")
  417. cur_li := self.MyList[self.PsIndex].(*WareHouseListItem)
  418. fmt.Println("Remove cur_li._Value",cur_li.Value)
  419. home_path, _ := os.UserHomeDir()
  420. if cur_li.Value["type"] == "source" {
  421. db, err := sql.Open("sqlite3", self.WareHouseDB)
  422. if err != nil {
  423. log.Fatal(err)
  424. }
  425. defer db.Close()
  426. _, err = db.Exec(fmt.Sprintf("DELETE FROM warehouse WHERE file = '%s'",
  427. cur_li.Value["file"]))
  428. if err != nil {
  429. log.Println(err)
  430. }
  431. } else if cur_li.Value["type"] == "launcher" ||
  432. cur_li.Value["type"] == "pico8" ||
  433. cur_li.Value["type"] == "tic80" {
  434. remote_file_url := cur_li.Value["file"]
  435. parts := strings.Split(remote_file_url,"raw.githubusercontent.com")
  436. menu_file := parts[1]
  437. local_menu_file := fmt.Sprintf(aria2dl_folder,home_path,menu_file)
  438. local_menu_file_path := filepath.Dir(local_menu_file)
  439. gid,ret := self.UrlIsDownloading(remote_file_url)
  440. if ret == true {
  441. self.rpcc.Remove(gid)
  442. }
  443. if UI.FileExists(local_menu_file) {
  444. os.Remove(local_menu_file)
  445. }
  446. if UI.FileExists(local_menu_file+".aria2") {
  447. os.Remove(local_menu_file+".aria2")
  448. }
  449. if UI.FileExists(filepath.Join(local_menu_file_path,cur_li.Value["title"])) {
  450. os.RemoveAll(filepath.Join(local_menu_file_path,cur_li.Value["title"]))
  451. }
  452. }
  453. }
  454. func (self *WareHouse) Click() {
  455. if self.PsIndex > len(self.MyList) -1 {
  456. return
  457. }
  458. cur_li := self.MyList[self.PsIndex].(*WareHouseListItem)
  459. home_path, _ := os.UserHomeDir()
  460. fmt.Println("Click cur_li._Value",cur_li.Value)
  461. if cur_li.Value["type"] == "source" || cur_li.Value["type"] == "dir" {
  462. remote_file_url := cur_li.Value["file"]
  463. parts := strings.Split(remote_file_url,"raw.githubusercontent.com")//assume master branch
  464. menu_file := parts[1]
  465. local_menu_file := fmt.Sprintf(aria2dl_folder,home_path,menu_file)
  466. fmt.Println("warehouse click: ",local_menu_file)
  467. if UI.FileExists(local_menu_file) == false {
  468. self.LoadHouse()
  469. }else {
  470. //read the local_menu_file,push into stack,display menu
  471. self.Aria2DownloadingGid = ""
  472. var result WareHouseIndex
  473. jsonFile, err := os.Open(local_menu_file)
  474. if err != nil {
  475. fmt.Println(err)
  476. self.Screen.MsgBox.SetText("Open House failed")
  477. self.Screen.MsgBox.Draw()
  478. self.Screen.SwapAndShow()
  479. }else {
  480. defer jsonFile.Close()
  481. byteValue, _ := ioutil.ReadAll(jsonFile)
  482. json.Unmarshal(byteValue, &result)
  483. self.MyStack.Push(result.List)
  484. self.SyncList()
  485. self.Screen.Refresh()
  486. }
  487. }
  488. } else if cur_li.Value["type"] == "add_house" {
  489. fmt.Println("show keyboard to add warehouse")
  490. self.Screen.PushCurPage()
  491. self.Screen.SetCurPage(self.Keyboard)
  492. } else {
  493. //download the game probably
  494. remote_file_url := cur_li.Value["file"]
  495. parts := strings.Split(remote_file_url,"raw.githubusercontent.com")//assume master branch
  496. menu_file := parts[1]
  497. local_menu_file := fmt.Sprintf(aria2dl_folder,home_path,menu_file)
  498. fmt.Println("Click on game ", local_menu_file)
  499. if UI.FileExists(local_menu_file) == false {
  500. gid,ret := self.UrlIsDownloading(remote_file_url)
  501. if ret == false {
  502. outfile := struct {
  503. Out string `json:"out"`
  504. }{Out:menu_file}
  505. gid,err := self.rpcc.AddURI([]string{remote_file_url},outfile)
  506. if err != nil {
  507. log.Println(err)
  508. }else {
  509. fmt.Println("Warehouse Click game is downloading, ",gid)
  510. fmt.Println(remote_file_url)
  511. self.Aria2DownloadingGid = gid
  512. }
  513. } else {
  514. fmt.Println(self.rpcc.TellStatus(gid,"status","totalLength","completedLength"))
  515. self.Screen.MsgBox.SetText("Getting the game now")
  516. self.Screen.MsgBox.Draw()
  517. self.Screen.SwapAndShow()
  518. time.BlockDelay(800)
  519. self.Screen.TitleBar.Redraw()
  520. }
  521. }else {
  522. fmt.Println("file downloaded ", cur_li.Value) //maybe check it if is installed fst,then execute it
  523. if cur_li.Value["type"] == "launcher" && cur_li.ReadOnly == false {
  524. local_menu_file_path := filepath.Dir(local_menu_file)
  525. game_sh := filepath.Join(local_menu_file_path,cur_li.Value["title"],cur_li.Value["title"]+".sh")
  526. fmt.Println("run game: ",game_sh, UI.FileExists(game_sh))
  527. self.Screen.RunEXE(game_sh)
  528. }
  529. if cur_li.Value["type"] == "pico8" && cur_li.ReadOnly == false {
  530. if UI.FileExists("/home/cpi/games/PICO-8/pico-8/pico8") {
  531. game_sh := "/home/cpi/launchergo/Menu/GameShell/50_PICO-8/PICO-8.sh"
  532. self.Screen.RunEXE(game_sh) //pico8 manages its games self
  533. }
  534. }
  535. if cur_li.Value["type"] == "tic80" && cur_li.ReadOnly == false {
  536. game_sh := "/home/cpi/apps/Menu/51_TIC-80/TIC-80.sh"
  537. self.Screen.RunEXE(game_sh)
  538. }
  539. }
  540. }
  541. }
  542. func (self *WareHouse) OnAria2CompleteCb(gid string) {
  543. fmt.Println("OnAria2CompleteCb", gid)
  544. self.SyncList()
  545. self.Screen.Refresh()
  546. if gid == self.Aria2DownloadingGid {
  547. self.Aria2DownloadingGid = ""
  548. }
  549. }
  550. func (self *WareHouse) raw_github_com(url string) (bool,string) {
  551. if strings.HasPrefix(url,"github.com") == false {
  552. return false,""
  553. }
  554. parts := strings.Split(url,"/")
  555. if len(parts) != 3 {
  556. return false, ""
  557. }
  558. str := []string{"https://raw.githubusercontent.com",
  559. parts[1],
  560. parts[2],
  561. "master/index.json"}
  562. return true,strings.Join(str,"/")
  563. }
  564. func (self *WareHouse) OnKbdReturnBackCb() {
  565. inputed:= strings.Join(self.Keyboard.Textarea.MyWords,"")
  566. inputed = strings.Replace(inputed,"http://","",-1)
  567. inputed = strings.Replace(inputed,"https://","",-1)
  568. if strings.HasSuffix(inputed,".git") {
  569. inputed = inputed[:len(inputed)-4]
  570. }
  571. if strings.HasSuffix(inputed,"/") {
  572. inputed = inputed[:len(inputed)-1]
  573. }
  574. fmt.Println("last: ",inputed)
  575. db, err := sql.Open("sqlite3", self.WareHouseDB)
  576. if err != nil {
  577. log.Fatal(err)
  578. return
  579. }
  580. defer db.Close()
  581. stmt, err := db.Prepare("SELECT count(*) FROM warehouse WHERE title= ?")
  582. defer stmt.Close()
  583. if err != nil {
  584. log.Fatal(err)
  585. }
  586. var cnt_str string
  587. cnt := 0
  588. err = stmt.QueryRow(inputed).Scan(&cnt_str)
  589. if err != nil {
  590. log.Println(err)
  591. cnt_str = "0"
  592. }else {
  593. cnt,_= strconv.Atoi(cnt_str)
  594. }
  595. if cnt > 0 {
  596. self.Screen.MsgBox.SetText("Warehouse existed")
  597. self.Screen.MsgBox.Draw()
  598. self.Screen.SwapAndShow()
  599. } else {
  600. if strings.Contains(inputed,"github.com/clockworkpi/warehouse") {
  601. self.Screen.MsgBox.SetText("Warehouse existed")
  602. self.Screen.MsgBox.Draw()
  603. self.Screen.SwapAndShow()
  604. }else {
  605. valid_,_url := self.raw_github_com(inputed)
  606. if valid_ == false {
  607. self.Screen.MsgBox.SetText("Warehouse url error!")
  608. self.Screen.MsgBox.Draw()
  609. self.Screen.SwapAndShow()
  610. } else {
  611. sql_insert := fmt.Sprintf("INSERT INTO warehouse(title,file,type) VALUES('%s','%s','source');",
  612. inputed,_url)
  613. _, err = db.Exec(sql_insert)
  614. if err != nil {
  615. log.Println(err)
  616. }
  617. self.SyncList()
  618. self.Screen.Refresh()
  619. }
  620. }
  621. }
  622. }
  623. func (self *WareHouse) OnExitCb() {
  624. self.SetDownloading(false)
  625. self.rpcc.Close()
  626. }
  627. func (self *WareHouse) OnLoadCb() {
  628. if self.MyStack.Length() == 1 {
  629. self.FootMsg[2] = "Remove"
  630. self.FootMsg[1] = "Update"
  631. }else {
  632. self.FootMsg[2] = "Remove"
  633. self.FootMsg[1] = "Preview"
  634. }
  635. self.SetDownloading(true)
  636. go self.UpdateProcessInterval(500)
  637. self.SyncList()
  638. }
  639. func (self *WareHouse) OnReturnBackCb() {
  640. if self.MyStack.Length() == 1 {
  641. self.FootMsg[2] = "Remove"
  642. self.FootMsg[1] = "Update"
  643. }else {
  644. self.FootMsg[2] = "Remove"
  645. self.FootMsg[1] = "Preview"
  646. }
  647. self.SyncList()
  648. self.RestoreScrolled()
  649. self.Screen.Refresh()
  650. }
  651. func (self *WareHouse) ScrollDown() {
  652. if len(self.MyList) == 0 {
  653. return
  654. }
  655. self.PsIndex += 1
  656. if self.PsIndex >= len(self.MyList) {
  657. self.PsIndex = len(self.MyList) - 1
  658. }
  659. cur_li := self.MyList[self.PsIndex]
  660. x, y := cur_li.Coord()
  661. _, h := cur_li.Size()
  662. if y+h > self.Height {
  663. for i, _ := range self.MyList {
  664. x, y = self.MyList[i].Coord()
  665. _, h = self.MyList[i].Size()
  666. self.MyList[i].NewCoord(x, y-h)
  667. }
  668. self.ScrolledCnt -= h
  669. }
  670. }
  671. func (self *WareHouse) ScrollUp() {
  672. if len(self.MyList) == 0 {
  673. return
  674. }
  675. self.PsIndex -= 1
  676. if self.PsIndex < 0 {
  677. self.PsIndex = 0
  678. }
  679. cur_li := self.MyList[self.PsIndex]
  680. x, y := cur_li.Coord()
  681. _, h := cur_li.Size()
  682. if y < 0 {
  683. for i, _ := range self.MyList {
  684. x, y = self.MyList[i].Coord()
  685. _, h = self.MyList[i].Size()
  686. self.MyList[i].NewCoord(x, y+h)
  687. }
  688. self.ScrolledCnt += h
  689. }
  690. }
  691. func (self *WareHouse) RestoreScrolled() {
  692. for i,_ := range self.MyList {
  693. x,y := self.MyList[i].Coord()
  694. self.MyList[i].NewCoord(x, y+ self.ScrolledCnt)
  695. }
  696. }
  697. func (self *WareHouse) KeyDown(ev *event.Event) {
  698. if UI.IsKeyMenuOrB(ev.Data["Key"]) {
  699. if self.MyStack.Length() > 1 {
  700. self.MyStack.Pop()
  701. if self.MyStack.Length() == 1 {
  702. self.FootMsg[2] = "Remove"
  703. self.FootMsg[1] = "Update"
  704. }else {
  705. self.FootMsg[2] = "Remove"
  706. self.FootMsg[1] = "Preview"
  707. if self.MyStack.Length() == 2 {
  708. self.FootMsg[2] = ""
  709. self.FootMsg[1] = ""
  710. }
  711. }
  712. self.SyncList()
  713. self.Screen.Refresh()
  714. }else if self.MyStack.Length() == 1 {
  715. self.ReturnToUpLevelPage()
  716. self.Screen.Refresh()
  717. self.SetDownloading(false)//shutdown UpdateProcessInterval
  718. }
  719. }
  720. if UI.IsKeyStartOrA(ev.Data["Key"]) {
  721. self.Click()
  722. if self.MyStack.Length() == 1 {
  723. self.FootMsg[2] = "Remove"
  724. self.FootMsg[1] = "Update"
  725. }else {
  726. self.FootMsg[2] = "Remove"
  727. self.FootMsg[1] = "Preview"
  728. if self.MyStack.Length() == 2 {
  729. self.FootMsg[2] = ""
  730. self.FootMsg[1] = ""
  731. }
  732. }
  733. self.Screen.Refresh()
  734. }
  735. if ev.Data["Key"] == UI.CurKeys["X"] {
  736. if self.PsIndex <= len(self.MyList) -1 {
  737. cur_li := self.MyList[self.PsIndex].(*WareHouseListItem)
  738. if cur_li.Type != "dir" {
  739. if self.MyStack.Length() ==1 && self.PsIndex == 0 {
  740. //pass
  741. }else {
  742. self.Screen.PushPage(self.RemovePage)
  743. self.RemovePage.StartOrAEvent = self.RemoveGame
  744. self.Screen.Refresh()
  745. }
  746. }
  747. return
  748. }
  749. self.SyncList()
  750. self.Screen.Refresh()
  751. }
  752. if ev.Data["Key"] == UI.CurKeys["Y"] {
  753. if self.MyStack.Length() == 1 {
  754. self.ResetHouse()
  755. }else {
  756. self.PreviewGame()
  757. }
  758. }
  759. if ev.Data["Key"] == UI.CurKeys["Up"] {
  760. self.ScrollUp()
  761. self.Screen.Refresh()
  762. }
  763. if ev.Data["Key"] == UI.CurKeys["Down"] {
  764. self.ScrollDown()
  765. self.Screen.Refresh()
  766. }
  767. }
  768. func (self *WareHouse) Draw() {
  769. self.ClearCanvas()
  770. if self.PsIndex > len(self.MyList) -1 {
  771. self.PsIndex = len(self.MyList) -1
  772. }
  773. if self.PsIndex < 0 {
  774. self.PsIndex = 0
  775. }
  776. if len(self.MyList) == 0 {
  777. return
  778. } else {
  779. if len(self.MyList) * UI.DefaultInfoPageListItemHeight > self.Height {
  780. _,h := self.Ps.Size()
  781. self.Ps.NewSize(self.Width - 11,h)
  782. self.Ps.Draw()
  783. for _,v := range self.MyList {
  784. _,y := v.Coord()
  785. if y > (self.Height + self.Height/2) {
  786. break
  787. }
  788. if y < 0 {
  789. continue
  790. }
  791. v.Draw()
  792. }
  793. self.Scroller.UpdateSize(len(self.MyList)*UI.DefaultInfoPageListItemHeight,self.PsIndex*UI.DefaultInfoPageListItemHeight)
  794. self.Scroller.Draw()
  795. }else {
  796. _,h := self.Ps.Size()
  797. self.Ps.NewSize(self.Width,h)
  798. self.Ps.Draw()
  799. for _,v := range self.MyList {
  800. _,y := v.Coord()
  801. if y > self.Height + self.Height/2 {
  802. break
  803. }
  804. if y < 0 {
  805. continue
  806. }
  807. v.Draw()
  808. }
  809. }
  810. }
  811. if self.HWND != nil {
  812. surface.Fill(self.HWND, UI.MySkinManager.GiveColor("White"))
  813. rect_ := rect.Rect(self.PosX, self.PosY, self.Width, self.Height)
  814. surface.Blit(self.HWND, self.CanvasHWND, &rect_, nil)
  815. }
  816. }