2022-05-21 00:49:13 +02:00
// Copyright 2022 wanderer <a_mirre at utb dot cz>
// SPDX-License-Identifier: GPL-3.0-or-later
2022-05-19 17:24:00 +02:00
package xkcdreader
import (
2022-05-25 23:33:27 +02:00
"fmt"
2022-05-23 00:49:04 +02:00
"log"
2022-05-26 20:42:35 +02:00
"os"
2022-05-25 23:33:27 +02:00
"time"
2022-05-23 00:49:04 +02:00
2022-05-21 01:18:06 +02:00
"fyne.io/fyne/v2"
2022-05-19 17:24:00 +02:00
"fyne.io/fyne/v2/app"
2022-05-26 20:42:35 +02:00
"fyne.io/fyne/v2/canvas"
2022-05-21 01:18:06 +02:00
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/layout"
2022-05-30 18:08:30 +02:00
"fyne.io/fyne/v2/storage"
2022-05-23 00:49:04 +02:00
"fyne.io/fyne/v2/theme"
2022-05-19 17:24:00 +02:00
"fyne.io/fyne/v2/widget"
"git.dotya.ml/wanderer/go-xkcdreader/cmd"
2022-05-30 18:08:30 +02:00
"git.dotya.ml/wanderer/go-xkcdreader/xkcdreader/xkcd"
2022-05-19 17:24:00 +02:00
)
const appGreeting = "welcome to go-xkcdreader"
2022-05-30 18:08:30 +02:00
var (
a fyne . App
latestComic = xkcd . GetLatest ( )
)
2022-05-23 17:56:24 +02:00
2022-05-27 22:14:29 +02:00
// RunApp performs sets up and runs the main application.
2022-05-19 17:24:00 +02:00
func RunApp ( ) {
2022-05-23 17:56:24 +02:00
// initialize the fyne application
newApp ( )
goxkcdreader := getApp ( )
w := goxkcdreader . NewWindow ( cmd . GetAppName ( ) )
2022-05-19 17:24:00 +02:00
2022-05-27 17:43:35 +02:00
// mark this window as the main window
w . SetMaster ( )
2022-05-23 16:54:31 +02:00
centered := container . New (
layout . NewHBoxLayout ( ) ,
layout . NewSpacer ( ) ,
makeGreeting ( ) ,
layout . NewSpacer ( ) ,
)
w . SetContent ( container . New (
layout . NewVBoxLayout ( ) ,
makeToolbar ( ) ,
centered ,
makeTabs ( ) ,
) )
2022-05-19 17:24:00 +02:00
2022-05-21 01:18:06 +02:00
w . Resize ( fyne . NewSize ( 400 , 400 ) )
2022-05-19 17:24:00 +02:00
w . ShowAndRun ( )
}
2022-05-23 17:56:24 +02:00
func newApp ( ) {
a = app . New ( )
2022-05-27 23:08:17 +02:00
2022-05-23 17:56:24 +02:00
log . Println ( "Created a new fyne application" )
}
func getApp ( ) fyne . App {
return a
}
2022-05-27 22:14:29 +02:00
// makeGreeting creates a greeting label.
2022-05-19 17:24:00 +02:00
func makeGreeting ( ) * widget . Label {
2022-05-21 01:18:06 +02:00
w := widget . NewLabel ( appGreeting )
w . TextStyle . Monospace = true
2022-05-27 23:08:17 +02:00
2022-05-21 01:18:06 +02:00
return w
2022-05-19 17:24:00 +02:00
}
2022-05-23 00:49:04 +02:00
func makeToolbar ( ) * widget . Toolbar {
toolbar := widget . NewToolbar (
widget . NewToolbarSpacer ( ) ,
widget . NewToolbarAction ( theme . HelpIcon ( ) , func ( ) {
log . Println ( "Display help" )
} ) ,
widget . NewToolbarAction ( theme . SettingsIcon ( ) , func ( ) {
log . Println ( "Display settings" )
} ) ,
2022-05-24 23:27:39 +02:00
widget . NewToolbarAction ( theme . InfoIcon ( ) , aboutWindow ) ,
2022-05-23 00:49:04 +02:00
)
2022-05-27 23:08:17 +02:00
2022-05-23 00:49:04 +02:00
return toolbar
}
2022-05-23 01:23:03 +02:00
func makeTabs ( ) * container . AppTabs {
tabs := container . NewAppTabs (
2022-05-25 23:33:27 +02:00
container . NewTabItem ( "browse" , makeBrowseUI ( ) ) ,
2022-05-23 01:23:03 +02:00
container . NewTabItem ( "what if?" , widget . NewLabel ( "serious answers to absurd questions and absurd advice for common concerns from xkcd's Randall Munroe" ) ) ,
2022-05-25 22:31:09 +02:00
container . NewTabItemWithIcon ( "search" , theme . SearchIcon ( ) , makeSearchTab ( ) ) ,
2022-05-23 01:23:03 +02:00
)
2022-05-27 23:08:17 +02:00
2022-05-23 01:23:03 +02:00
return tabs
}
2022-05-23 17:04:56 +02:00
func makeBrowseUI ( ) * fyne . Container {
// container for the image and surrounding elements
imgC := container . New (
layout . NewHBoxLayout ( ) ,
2022-05-25 18:59:13 +02:00
widget . NewButtonWithIcon ( "" , theme . NavigateBackIcon ( ) , func ( ) {
2022-05-23 17:04:56 +02:00
log . Println ( "Previous comic" )
} ) ,
layout . NewSpacer ( ) ,
2022-05-26 20:42:35 +02:00
container . NewCenter (
// TODO(me): dynamically replace placeholder text with image once
// fetched...
// widget.NewLabel("img placeholder"),
2022-05-30 18:08:30 +02:00
getImg ( latestComic . Img , false ) ,
2022-05-26 20:42:35 +02:00
) ,
2022-05-23 17:04:56 +02:00
layout . NewSpacer ( ) ,
2022-05-25 18:59:13 +02:00
widget . NewButtonWithIcon ( "" , theme . NavigateNextIcon ( ) , func ( ) {
2022-05-23 17:04:56 +02:00
log . Println ( "Next comic" )
2022-05-28 16:54:45 +02:00
} ) ,
)
2022-05-23 17:04:56 +02:00
browseUI := container . New (
layout . NewVBoxLayout ( ) ,
layout . NewSpacer ( ) ,
2022-05-25 23:33:27 +02:00
container . NewCenter (
container . NewVBox (
& widget . Label { Text : "published on " + fmt . Sprint ( time . Now ( ) . Date ( ) ) , TextStyle : fyne . TextStyle { Italic : true } } ,
container . NewHBox (
& widget . Label { Text : "Comic Title" , TextStyle : fyne . TextStyle { Bold : true } } ,
& widget . Label { Text : "(#1234)" , TextStyle : fyne . TextStyle { Monospace : true } } ,
) ,
) ,
) ,
2022-05-23 17:04:56 +02:00
imgC ,
2022-05-25 23:33:27 +02:00
layout . NewSpacer ( ) ,
container . NewCenter (
& widget . Label { Text : "Comic 'title text'" , TextStyle : fyne . TextStyle { Italic : true } } ,
) ,
2022-05-23 17:04:56 +02:00
)
return browseUI
}
2022-05-26 20:42:35 +02:00
2022-05-30 18:08:30 +02:00
// getComicLatest fetches latest comic, updates latestComic if necessary.
func getComicLatest ( ) {
comic := xkcd . GetLatest ( )
if comic == nil {
// TODO(me): properly handle the situation (i.e. bail early)
log . Println ( "error getting latest comic" )
}
// update latesComic, if necessary
if latestComic != comic {
latestComic = comic
}
}
2022-05-27 22:14:29 +02:00
// get img from filesystem, resize it and return as *canvas.Image.
2022-05-30 18:08:30 +02:00
func getImg ( imgURI string , local bool ) * canvas . Image {
if local {
_ , err := os . Stat ( imgURI )
// properly handle error, perhaps panic?...don't panic, I know..
if err != nil {
log . Println ( "failed to read file " + imgURI )
return canvas . NewImageFromFile ( "" )
}
img := canvas . NewImageFromFile ( imgURI )
img . SetMinSize (
fyne . Size {
Height : 383 ,
Width : 273 ,
} ,
)
img . ScaleMode = canvas . ImageScaleSmooth
img . FillMode = canvas . ImageFillContain
return img
}
preImg , err := storage . ParseURI ( imgURI )
2022-05-26 20:42:35 +02:00
if err != nil {
2022-05-30 18:08:30 +02:00
log . Printf ( "error parsing comic URI: %q" , err . Error ( ) )
2022-05-26 20:42:35 +02:00
}
2022-05-30 18:08:30 +02:00
// get the actual image
img := canvas . NewImageFromURI ( preImg )
2022-05-26 20:42:35 +02:00
2022-05-30 18:08:30 +02:00
if img . Resource == nil {
log . Println ( "error fetching the image file of the latest comic" )
}
// set basic img properties
2022-05-26 20:42:35 +02:00
img . SetMinSize (
fyne . Size {
2022-05-30 18:08:30 +02:00
// subject to change, this is what I consider to be sane defaults
// atm...
Height : 650 ,
Width : 750 ,
2022-05-26 20:42:35 +02:00
} ,
)
2022-05-30 18:08:30 +02:00
img . ScaleMode = canvas . ImageScaleSmooth
img . FillMode = canvas . ImageFillContain
2022-05-26 20:42:35 +02:00
return img
}