diff --git a/go.mod b/go.mod index e4a338329..925eeb6c3 100644 --- a/go.mod +++ b/go.mod @@ -4,7 +4,7 @@ go 1.19 require ( codeberg.org/sdassow/unyts v0.4.1 - fyne.io/fyne/v2 v2.7.3 + fyne.io/fyne/v2 v2.7.4-0.20260406093139-56b2442450ac github.com/BurntSushi/toml v1.5.0 // indirect github.com/BurntSushi/xgb v0.0.0-20210121224620-deaf085860bc github.com/BurntSushi/xgbutil v0.0.0-20190907113008-ad855c713046 @@ -45,18 +45,21 @@ require ( github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78 // indirect github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298 // indirect github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966 // indirect + github.com/anthonynsimon/bild v0.13.0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/fredbi/uri v1.1.1 // indirect github.com/fsnotify/fsnotify v1.9.0 // indirect - github.com/fyne-io/gl-js v0.2.0 // indirect + github.com/fyne-io/gl-js v0.2.1-0.20260315212741-029c47fd27e8 // indirect github.com/fyne-io/glfw-js v0.3.0 // indirect github.com/go-gl/gl v0.0.0-20231021071112-07e5d0ea2e71 // indirect github.com/go-gl/glfw/v3.3/glfw v0.0.0-20240506104042-037f3cc74f2a // indirect github.com/go-text/render v0.2.1 // indirect github.com/go-text/typesetting v0.3.4 // indirect github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25 // indirect + github.com/mattn/go-runewidth v0.0.17 // indirect github.com/pkg/errors v0.8.1 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rivo/uniseg v0.2.0 // indirect github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c // indirect github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef // indirect github.com/yuin/goldmark v1.7.8 // indirect diff --git a/go.sum b/go.sum index 38e0e314a..df18d6ff7 100644 --- a/go.sum +++ b/go.sum @@ -1,7 +1,7 @@ codeberg.org/sdassow/unyts v0.4.1 h1:nLYkLu0E1tO9+6mKzGFf3aDaV0YSiR2msous9t5LQ0Y= codeberg.org/sdassow/unyts v0.4.1/go.mod h1:VlI7KnjFURzz7TQNla4308PgEUt4VVrfYbf0AGiqyoI= -fyne.io/fyne/v2 v2.7.3 h1:xBT/iYbdnNHONWO38fZMBrVBiJG8rV/Jypmy4tVfRWE= -fyne.io/fyne/v2 v2.7.3/go.mod h1:gu+dlIcZWSzKZmnrY8Fbnj2Hirabv2ek+AKsfQ2bBlw= +fyne.io/fyne/v2 v2.7.4-0.20260406093139-56b2442450ac h1:R/yT+trqfgV8Tw5bkLmKgbIRGl3/H5BfsN1FCeDvv48= +fyne.io/fyne/v2 v2.7.4-0.20260406093139-56b2442450ac/go.mod h1:3FRSe4wPFsT9iFAH/HKZf6b7zqBQXupvIRJ9mTz/k90= fyne.io/systray v1.12.0 h1:CA1Kk0e2zwFlxtc02L3QFSiIbxJ/P0n582YrZHT7aTM= fyne.io/systray v1.12.0/go.mod h1:RVwqP9nYMo7h5zViCBHri2FgjXF7H2cub7MAq4NSoLs= github.com/ActiveState/termtest/conpty v0.5.0 h1:JLUe6YDs4Jw4xNPCU+8VwTpniYOGeKzQg4SM2YHQNA8= @@ -12,6 +12,7 @@ github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298 h1:1qlsVAQJ github.com/BurntSushi/freetype-go v0.0.0-20160129220410-b763ddbfe298/go.mod h1:D+QujdIlUNfa0igpNMk6UIvlb6C252URs4yupRUV4lQ= github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966 h1:lTG4HQym5oPKjL7nGs+csTgiDna685ZXjxijkne828g= github.com/BurntSushi/graphics-go v0.0.0-20160129215708-b43f31a4a966/go.mod h1:Mid70uvE93zn9wgF92A/r5ixgnvX8Lh68fxp9KQBaI0= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.5.0 h1:W5quZX/G/csjUnuI8SUYlsHs9M38FC7znL0lIO+DvMg= github.com/BurntSushi/toml v1.5.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= github.com/FyshOS/appie v0.1.0 h1:B9CD2ZufCAPTFaE18fbUvuasAYC22bzoh4C8fmvXMno= @@ -28,8 +29,16 @@ github.com/FyshOS/saver v0.1.1-0.20260407200543-762135717028 h1:gnZOxK+y64+zaAre github.com/FyshOS/saver v0.1.1-0.20260407200543-762135717028/go.mod h1:WvBivsR68hbiahFFjEf5Yzv1chBd/Slo8TRziPgzEOY= github.com/Knetic/govaluate v3.0.0+incompatible h1:7o6+MAPhYTCF0+fdvoz1xDedhRb4f6s9Tn1Tt7/WTEg= github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/anthonynsimon/bild v0.13.0 h1:mN3tMaNds1wBWi1BrJq0ipDBhpkooYfu7ZFSMhXt1C8= +github.com/anthonynsimon/bild v0.13.0/go.mod h1:tpzzp0aYkAsMi1zmfhimaDyX1xjn2OUc1AJZK/TF0AE= +github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= +github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= github.com/creack/pty v1.1.21 h1:1/QdRyBaHHJP61QkWMXlOIBfsgdDeeKfK8SYVUWJKf0= github.com/creack/pty v1.1.21/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= +github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c= @@ -37,10 +46,11 @@ github.com/disintegration/imaging v1.6.2/go.mod h1:44/5580QXChDfwIclfc/PCwrr44am github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= github.com/fredbi/uri v1.1.1 h1:xZHJC08GZNIUhbP5ImTHnt5Ya0T8FI2VAwI/37kh2Ko= github.com/fredbi/uri v1.1.1/go.mod h1:4+DZQ5zBjEwQCDmXW5JdIjz0PUA+yJbvtBv+u+adr5o= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/fyne-io/gl-js v0.2.0 h1:+EXMLVEa18EfkXBVKhifYB6OGs3HwKO3lUElA0LlAjs= -github.com/fyne-io/gl-js v0.2.0/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI= +github.com/fyne-io/gl-js v0.2.1-0.20260315212741-029c47fd27e8 h1:0kdPD/GEntpWmZEK5Zu/xE6Tr37jYCVDf9QP8lA/QK8= +github.com/fyne-io/gl-js v0.2.1-0.20260315212741-029c47fd27e8/go.mod h1:ZcepK8vmOYLu96JoxbCKJy2ybr+g1pTnaBDdl7c3ajI= github.com/fyne-io/glfw-js v0.3.0 h1:d8k2+Y7l+zy2pc7wlGRyPfTgZoqDf3AI4G+2zOWhWUk= github.com/fyne-io/glfw-js v0.3.0/go.mod h1:Ri6te7rdZtBgBpxLW19uBpp3Dl6K9K/bRaYdJ22G8Jk= github.com/fyne-io/image v0.1.1 h1:WH0z4H7qfvNUw5l4p3bC1q70sa5+YWVt6HCj7y4VNyA= @@ -69,6 +79,8 @@ github.com/hack-pad/go-indexeddb v0.3.2 h1:DTqeJJYc1usa45Q5r52t01KhvlSN02+Oq+tQb github.com/hack-pad/go-indexeddb v0.3.2/go.mod h1:QvfTevpDVlkfomY498LhstjwbPW6QC4VC/lxYb0Kom0= github.com/hack-pad/safejs v0.1.0 h1:qPS6vjreAqh2amUqj4WNG1zIw7qlRQJ9K10eDKMCnE8= github.com/hack-pad/safejs v0.1.0/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio= +github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jackmordaunt/icns v1.0.1-0.20200413110149-9e181b441ab2 h1:2bRhR5GcMudCdaY4p8ip89hsvSyxYehLSicCNtygyVY= github.com/jackmordaunt/icns v1.0.1-0.20200413110149-9e181b441ab2/go.mod h1:Hj3TV9xrdt+g9apvBagVi/VzE41gSliEBypxaQDq5QA= github.com/jeandeaual/go-locale v0.0.0-20250612000132-0ef82f21eade h1:FmusiCI1wHw+XQbvL9M+1r/C3SPqKrmBaIOYwVfQoDE= @@ -79,34 +91,53 @@ github.com/jsummers/gobmp v0.0.0-20230614200233-a9de23ed2e25/go.mod h1:kLgvv7o6U github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/mafik/pulseaudio v0.0.0-20200511091429-8449222912dd h1:gn6oLpDCn3wY+1WfbbP0OwxXL+2eHi3mxF/DsNyPHUM= github.com/mafik/pulseaudio v0.0.0-20200511091429-8449222912dd/go.mod h1:dlpd1fnLAhI6g9tM/aCobgN/Yka1/SkHrBTfAgDdb9Q= +github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= +github.com/mattn/go-runewidth v0.0.17 h1:78v8ZlW0bP43XfmAfPsdXcoNCelfMHsDmd/pkENfrjQ= +github.com/mattn/go-runewidth v0.0.17/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= github.com/nicksnyder/go-i18n/v2 v2.5.1 h1:IxtPxYsR9Gp60cGXjfuR/llTqV8aYMsC472zD0D1vHk= github.com/nicksnyder/go-i18n/v2 v2.5.1/go.mod h1:DrhgsSDZxoAfvVrBVLXoxZn/pN5TXqaDbq7ju94viiQ= github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= +github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= +github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= github.com/rymdport/portal v0.4.2 h1:7jKRSemwlTyVHHrTGgQg7gmNPJs88xkbKcIL3NlcmSU= github.com/rymdport/portal v0.4.2/go.mod h1:kFF4jslnJ8pD5uCi17brj/ODlfIidOxlgUDTO5ncnC4= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= +github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= +github.com/spf13/cobra v0.0.5/go.mod h1:3K3wKZymM7VvHMDS9+Akkh4K60UwM26emMESw8tLCHU= +github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo= github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c h1:km8GpoQut05eY3GiYWEedbTT0qnSxrCjsVbb7yKY1KE= github.com/srwiley/oksvg v0.0.0-20221011165216-be6e8873101c/go.mod h1:cNQ3dwVJtS5Hmnjxy6AgTPd0Inb3pW05ftPSX7NZO7Q= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef h1:Ch6Q+AZUxDBCVqdkI8FSpFyZDtCVBc2VmejdNrm5rRQ= github.com/srwiley/rasterx v0.0.0-20220730225603-2ab79fcdd4ef/go.mod h1:nXTWP6+gD5+LUJ8krVhhoeHjvHTutPxMYl5SvkcnJNE= +github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= +github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= +github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/yuin/goldmark v1.7.8 h1:iERMLn0/QJeHFhxSt3p6PeN9mGnvIKSpG9YYorDMnic= github.com/yuin/goldmark v1.7.8/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/image v0.0.0-20190703141733-d6a02ce849c9/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.24.0 h1:AN7zRgVsbvmTfNyqIbbOraYL8mSwcKncEj8ofjgzcMQ= golang.org/x/image v0.24.0/go.mod h1:4b/ITuLfqYq1hqZcjofwctIhi7sZh2WaCjvsBNjjya8= golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= +golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20200428200454-593003d681fa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= @@ -116,6 +147,7 @@ golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM= diff --git a/internal/ui/launcher.go b/internal/ui/launcher.go index 68b27dc41..6a6bab845 100644 --- a/internal/ui/launcher.go +++ b/internal/ui/launcher.go @@ -2,6 +2,7 @@ package ui import ( "image/color" + "strings" "github.com/FyshOS/appie" @@ -182,7 +183,7 @@ func (l *picker) loadIcons(dataRange []appie.AppData, appList []fyne.CanvasObjec } func (l *picker) loadSuggestionsMatching(input string) []fyne.CanvasObject { - var suggestList []fyne.CanvasObject + var suggestList, searchList []fyne.CanvasObject for _, m := range l.desk.Modules() { suggest, ok := m.(fynedesk.LaunchSuggestionModule) @@ -197,11 +198,18 @@ func (l *picker) loadSuggestionsMatching(input string) []fyne.CanvasObject { launchData.Launch() }) - suggestList = append(suggestList, button) + if strings.Contains(strings.ToLower(m.Metadata().Name), "search") { + searchList = append(searchList, button) + } else { + suggestList = append(suggestList, button) + } } } - return suggestList + if len(searchList) == 0 { + return searchList + } + return append(suggestList, searchList...) } func newAppPicker(callback func(appie.AppData, int)) *picker { diff --git a/internal/ui/settings.go b/internal/ui/settings.go index f9bb29688..07e4a29ae 100644 --- a/internal/ui/settings.go +++ b/internal/ui/settings.go @@ -274,9 +274,9 @@ func (d *deskSettings) load() { d.launcherZoomScale = 2.0 } - defaultModules := "Battery|Brightness|Sound|Launcher: Calculate|Launcher: Convert units|Launcher: Open URLs|Network|Virtual Desktops|SystemTray|Terminal Overlay|Desktop Files" + defaultModules := "Battery|Brightness|Sound|Launcher: Calculate|Launcher: Convert units|Launcher: Large Type|Launcher: Open URLs|Network|Virtual Desktops|SystemTray|Terminal Overlay|Desktop Files" if runtime.GOOS == "darwin" || runtime.GOOS == "windows" { // testing - defaultModules = "Battery|Brightness|Sound|Launcher: Calculate|Launcher: Open URLs|Network|Virtual Desktops" + defaultModules = "Battery|Brightness|Sound|Launcher: Calculate|Launcher: Large Type|Launcher: Open URLs|Network|Virtual Desktops" } moduleNames := fyne.CurrentApp().Preferences().StringWithFallback("modulenames", defaultModules) if moduleNames != "" { diff --git a/modules/launcher/init.go b/modules/launcher/init.go index b735d621b..c3d159906 100644 --- a/modules/launcher/init.go +++ b/modules/launcher/init.go @@ -4,6 +4,8 @@ import "fyshos.com/fynedesk" func init() { fynedesk.RegisterModule(calcMeta) + fynedesk.RegisterModule(largeTypeMeta) + fynedesk.RegisterModule(searchMeta) fynedesk.RegisterModule(urlMeta) fynedesk.RegisterModule(unytsMeta) } diff --git a/modules/launcher/largetype.go b/modules/launcher/largetype.go new file mode 100644 index 000000000..0e9aa9c49 --- /dev/null +++ b/modules/launcher/largetype.go @@ -0,0 +1,129 @@ +package launcher + +import ( + _ "embed" + "image/color" + "strings" + + "fyne.io/fyne/v2" + "fyne.io/fyne/v2/canvas" + "fyne.io/fyne/v2/container" + "fyne.io/fyne/v2/theme" + "fyne.io/fyne/v2/widget" + + "fyshos.com/fynedesk" +) + +var largeTypeAliases = []string{"largetype", "large", "big", "bigtype", "type"} + +var largeTypeMeta = fynedesk.ModuleMetadata{ + Name: "Launcher: Large Type", + NewInstance: newLargeType, +} + +//go:embed largetype.svg +var resourceLargeTypeSvgData []byte + +var resourceLargeType = &fyne.StaticResource{ + StaticName: "largetype.svg", + StaticContent: resourceLargeTypeSvgData, +} + +type largeType struct{} + +func (l *largeType) Destroy() { +} + +func (l *largeType) Metadata() fynedesk.ModuleMetadata { + return largeTypeMeta +} + +func (l *largeType) LaunchSuggestions(input string) []fynedesk.LaunchSuggestion { + lower := strings.ToLower(input) + + for _, alias := range largeTypeAliases { + prefix := alias + " " + if strings.HasPrefix(lower, prefix) { + text := input[len(prefix):] + return []fynedesk.LaunchSuggestion{&largeTypeItem{text: text}} + } + if strings.HasPrefix(alias, lower) { + return []fynedesk.LaunchSuggestion{&largeTypeItem{}} + } + } + + return nil +} + +func newLargeType() fynedesk.Module { + return &largeType{} +} + +type largeTypeItem struct { + text string +} + +func (i *largeTypeItem) Icon() fyne.Resource { + return theme.NewThemedResource(resourceLargeType) +} + +func (i *largeTypeItem) Title() string { + return "Large Type: " + i.text +} + +func (i *largeTypeItem) Launch() { + desk := fynedesk.Instance() + screen := desk.Screens().Primary() + scale := screen.CanvasScale() + + screenW := float32(screen.Width) / scale + screenH := float32(screen.Height) / scale + + label := canvas.NewText(i.text, theme.Color(theme.ColorNameForeground)) + label.TextSize = 120 + label.Alignment = fyne.TextAlignCenter + label.TextStyle = fyne.TextStyle{Bold: true} + + r, g, b, _ := theme.Color(theme.ColorNameOverlayBackground).RGBA() + bg := canvas.NewRectangle(&color.NRGBA{R: uint8(r >> 8), G: uint8(g >> 8), B: uint8(b >> 8), A: 0x80}) + + var overlay fyne.CanvasObject + dismiss := &largeTypeTappable{onTap: func() { + desk.HideOverlay(overlay) + }} + dismiss.ExtendBaseWidget(dismiss) + overlay = container.NewStack(canvas.NewBlur(5), bg, dismiss, container.NewCenter(label)) + + size := fyne.NewSize(screenW, screenH) + pos := fyne.NewPos(0, 0) + desk.ShowOverlay(overlay, size, pos) + fyne.Do(func() { + desk.Root().Canvas().Focus(dismiss) + }) +} + +// largeTypeTappable is a transparent widget that dismisses the overlay on tap. +type largeTypeTappable struct { + widget.BaseWidget + onTap func() +} + +func (t *largeTypeTappable) CreateRenderer() fyne.WidgetRenderer { + return widget.NewSimpleRenderer(canvas.NewRectangle(color.Transparent)) +} + +func (t *largeTypeTappable) Tapped(_ *fyne.PointEvent) { + if t.onTap != nil { + t.onTap() + } +} + +func (t *largeTypeTappable) FocusGained() {} +func (t *largeTypeTappable) FocusLost() {} +func (t *largeTypeTappable) TypedRune(rune) {} + +func (t *largeTypeTappable) TypedKey(_ *fyne.KeyEvent) { + if t.onTap != nil { + t.onTap() + } +} diff --git a/modules/launcher/largetype.svg b/modules/launcher/largetype.svg new file mode 100644 index 000000000..48647fef2 --- /dev/null +++ b/modules/launcher/largetype.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/modules/launcher/largetype_test.go b/modules/launcher/largetype_test.go new file mode 100644 index 000000000..a5498324d --- /dev/null +++ b/modules/launcher/largetype_test.go @@ -0,0 +1,48 @@ +package launcher + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestLargeType_LaunchSuggestions_NoMatch(t *testing.T) { + l := newLargeType().(*largeType) + + assert.Nil(t, l.LaunchSuggestions("hello world")) + assert.Nil(t, l.LaunchSuggestions("xyz")) +} + +func TestLargeType_LaunchSuggestions_AliasPrefix(t *testing.T) { + l := newLargeType().(*largeType) + + for _, alias := range largeTypeAliases { + res := l.LaunchSuggestions(alias) + if assert.Len(t, res, 1) { + item := res[0].(*largeTypeItem) + assert.Equal(t, "", item.text) + } + } + + // partial prefix still matches + res := l.LaunchSuggestions("lar") + if assert.Len(t, res, 1) { + assert.Equal(t, "", res[0].(*largeTypeItem).text) + } +} + +func TestLargeType_LaunchSuggestions_WithText(t *testing.T) { + l := newLargeType().(*largeType) + + res := l.LaunchSuggestions("largetype Hello World") + if assert.Len(t, res, 1) { + item := res[0].(*largeTypeItem) + assert.Equal(t, "Hello World", item.text) + assert.Equal(t, "Large Type: Hello World", item.Title()) + } + + res = l.LaunchSuggestions("BIG Fyne") + if assert.Len(t, res, 1) { + assert.Equal(t, "Fyne", res[0].(*largeTypeItem).text) + } +} diff --git a/modules/launcher/search.go b/modules/launcher/search.go new file mode 100644 index 000000000..5270da58f --- /dev/null +++ b/modules/launcher/search.go @@ -0,0 +1,61 @@ +package launcher + +import ( + "net/url" + "runtime/debug" + + "fyne.io/fyne/v2" + wmTheme "fyshos.com/fynedesk/theme" + + "fyshos.com/fynedesk" +) + +var searchMeta = fynedesk.ModuleMetadata{ + Name: "Launcher: Web Search", + NewInstance: newSearchSuggest, +} + +type search struct{} + +func (s *search) Destroy() { +} + +func (s *search) LaunchSuggestions(input string) []fynedesk.LaunchSuggestion { + if input == "" { + return nil + } + return []fynedesk.LaunchSuggestion{&searchItem{text: input}} +} + +func (s *search) Metadata() fynedesk.ModuleMetadata { + return searchMeta +} + +// newCalcSuggest creates a new module that will show an option to search the web for an string. +func newSearchSuggest() fynedesk.Module { + return &search{} +} + +type searchItem struct { + text string +} + +func (s *searchItem) Icon() fyne.Resource { + return wmTheme.InternetIcon +} + +func (s *searchItem) Title() string { + return "Search in Duck Duck Go" +} + +func (s *searchItem) Launch() { + enc := url.QueryEscape(s.text) + u, err := url.Parse("https://duck.com/?q=" + enc) + if err != nil { + fyne.LogError("Failed to set up web search", err) + return + } + + debug.PrintStack() + _ = fyne.CurrentApp().OpenURL(u) +} diff --git a/modules/launcher/search_test.go b/modules/launcher/search_test.go new file mode 100644 index 000000000..27b86aa26 --- /dev/null +++ b/modules/launcher/search_test.go @@ -0,0 +1,25 @@ +package launcher + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestSearch_LaunchSuggestions_Empty(t *testing.T) { + s := newSearchSuggest().(*search) + + assert.Nil(t, s.LaunchSuggestions("")) +} + +func TestSearch_LaunchSuggestions(t *testing.T) { + s := newSearchSuggest().(*search) + + res := s.LaunchSuggestions("fyne toolkit") + if assert.Len(t, res, 1) { + item := res[0].(*searchItem) + assert.Equal(t, "fyne toolkit", item.text) + assert.Equal(t, "Search in Duck Duck Go", item.Title()) + assert.NotNil(t, item.Icon()) + } +}