ware_house_page.go 22 KB

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