Browse Source

added library and initial commit for gui

0xdcarns 3 years ago
parent
commit
cd065e35f4

+ 11 - 0
go.mod

@@ -31,6 +31,7 @@ require (
 
 require (
 	filippo.io/edwards25519 v1.0.0-rc.1
+	fyne.io/fyne/v2 v2.1.4
 	github.com/guumaster/hostctl v1.1.2
 	github.com/kr/pretty v0.3.0
 	github.com/posthog/posthog-go v0.0.0-20211028072449-93c17c49e2b0
@@ -47,9 +48,15 @@ require (
 	github.com/docker/go-connections v0.4.0 // indirect
 	github.com/docker/go-units v0.4.0 // indirect
 	github.com/felixge/httpsnoop v1.0.1 // indirect
+	github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 // indirect
+	github.com/fsnotify/fsnotify v1.4.9 // indirect
+	github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f // indirect
+	github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211024062804-40e447a793be // indirect
 	github.com/go-playground/locales v0.14.0 // indirect
 	github.com/go-playground/universal-translator v0.18.0 // indirect
+	github.com/godbus/dbus/v5 v5.0.4 // indirect
 	github.com/gogo/protobuf v1.3.1 // indirect
+	github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff // indirect
 	github.com/google/go-cmp v0.5.7 // indirect
 	github.com/gorilla/websocket v1.4.2 // indirect
 	github.com/josharian/native v1.0.0 // indirect
@@ -66,7 +73,11 @@ require (
 	github.com/russross/blackfriday/v2 v2.1.0 // indirect
 	github.com/seancfoley/bintree v1.0.1 // indirect
 	github.com/spf13/afero v1.3.2 // indirect
+	github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 // indirect
+	github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 // indirect
 	github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c // indirect
+	github.com/yuin/goldmark v1.3.8 // indirect
+	golang.org/x/image v0.0.0-20200430140353-33d19683fad8 // indirect
 	golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
 	google.golang.org/appengine v1.4.0 // indirect
 	gopkg.in/yaml.v2 v2.4.0 // indirect

+ 52 - 2
go.sum

@@ -3,10 +3,15 @@ cloud.google.com/go v0.34.0 h1:eOI3/cP2VTU6uZLDYAoic+eyzzB9YyGmJ7eIjl8rOPg=
 cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
 filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
 filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
+fyne.io/fyne/v2 v2.1.4 h1:bt1+28++kAzRzPB0GM2EuSV4cnl8rXNX4cjfd8G06Rc=
+fyne.io/fyne/v2 v2.1.4/go.mod h1:p+E/Dh+wPW8JwR2DVcsZ9iXgR9ZKde80+Y+40Is54AQ=
 github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
+github.com/BurntSushi/toml v0.4.1/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
+github.com/Kodeworks/golang-image-ico v0.0.0-20141118225523-73f0f4cfade9/go.mod h1:7uhhqiBaR4CpN0k9rMjOtjpcfGd6DG2m04zQxKnWQ0I=
 github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
 github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
 github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
+github.com/akavel/rsrc v0.8.0/go.mod h1:uLoCtb9J+EyAqh+26kdrTgmzRBFPGOolLWKpdxkKq+c=
 github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
 github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
 github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
@@ -43,11 +48,20 @@ github.com/eclipse/paho.mqtt.golang v1.3.5 h1:sWtmgNxYM9P2sP+xEItMozsR3w0cqZFlqn
 github.com/eclipse/paho.mqtt.golang v1.3.5/go.mod h1:eTzb4gxwwyWpqBUHGQZ4ABAV7+Jgm1PklsYT/eo8Hcc=
 github.com/felixge/httpsnoop v1.0.1 h1:lvB5Jl89CsZtGIWuTcDM1E/vkVs49/Ml7JJe07l8SPQ=
 github.com/felixge/httpsnoop v1.0.1/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
+github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3 h1:FDqhDm7pcsLhhWl1QtD8vlzI4mm59llRvNzrFg6/LAA=
+github.com/fredbi/uri v0.0.0-20181227131451-3dcfdacbaaf3/go.mod h1:CzM2G82Q9BDUvMTGHnXf/6OExw/Dz2ivDj48nVg7Lg8=
 github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
+github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
+github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
 github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
+github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f h1:s0O46d8fPwk9kU4k1jj76wBquMVETx7uveQD9MCIQoU=
+github.com/go-gl/gl v0.0.0-20210813123233-e4099ee2221f/go.mod h1:wjpnOv6ONl2SuJSxqCPVaPZibGFdSci9HFocT9qtVYM=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211024062804-40e447a793be h1:Z28GdQBfKOL8tNHjvaDn3wHDO7AzTRkmAXvHvnopp98=
+github.com/go-gl/glfw/v3.3/glfw v0.0.0-20211024062804-40e447a793be/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
 github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
 github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
+github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
 github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
 github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
@@ -57,10 +71,14 @@ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl
 github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw=
 github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
 github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
+github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
+github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
 github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
 github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
 github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
+github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff h1:W71vTCKoxtdXgnm1ECDFkfQnpdqAO00zzGXLA5yaEX8=
+github.com/goki/freetype v0.0.0-20181231101311-fa8a33aabaff/go.mod h1:wfqRWLHRBsRgkp5dmbG56SA0DmVtwrF5N3oPdI8t+Aw=
 github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ=
 github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
 github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -97,7 +115,9 @@ github.com/guumaster/tablewriter v0.0.9 h1:qyswXhSCI1SWYH78MLApi8AfL8JsWZWAUkZLO
 github.com/guumaster/tablewriter v0.0.9/go.mod h1:9B1xy1BLPtcVAeYjC1EXPxcklqnzk7dU2c3ywGbUnKY=
 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 v0.0.0-20181231085925-4f16af745526/go.mod h1:UQkeMHVoNcyXYq9otUupF7/h/2tmHlhrS2zw7ZVvUqc=
 github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
+github.com/josephspurrier/goversioninfo v0.0.0-20200309025242-14b0ab84c6ca/go.mod h1:eJTEwMjXb7kZ633hO3Ln9mBUCOjX2+FlTljvpl9SYdE=
 github.com/josharian/native v1.0.0 h1:Ts/E8zCSEsG17dUqv7joXJFybuMLjQfWE04tsBODTxk=
 github.com/josharian/native v1.0.0/go.mod h1:7X/raswPFr05uY3HiLlYeyQntB6OO7E/d2Cu7qoaN2w=
 github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
@@ -119,6 +139,7 @@ github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
 github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
 github.com/lib/pq v1.10.5 h1:J+gdV2cUmX7ZqL2B0lFcW0m+egaHC2V3lpO8nWxyYiQ=
 github.com/lib/pq v1.10.5/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
+github.com/lucor/goinfo v0.0.0-20210802170112-c078a2b0f08b/go.mod h1:PRq09yoB+Q2OJReAmwzKivcYyremnibWGbK7WfftHzc=
 github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
 github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
 github.com/mattn/go-runewidth v0.0.7/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI=
@@ -138,6 +159,8 @@ github.com/mikioh/ipaddr v0.0.0-20190404000644-d465c8ab6721/go.mod h1:Ickgr2WtCL
 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/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
+github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
+github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
 github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
@@ -195,6 +218,10 @@ github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnIn
 github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
 github.com/spf13/viper v1.4.0/go.mod h1:PTJ7Z/lr49W6bUbkmS1V3by4uWynFiR9p7+dSq/yZzE=
+github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564 h1:HunZiaEKNGVdhTRQOVpMmj5MQnGnv+e8uZNu3xFLgyM=
+github.com/srwiley/oksvg v0.0.0-20200311192757-870daf9aa564/go.mod h1:afMbS0qvv1m5tfENCwnOdZGOF8RGR/FsZ7bvBxQGZG4=
+github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9 h1:m59mIOBO4kfcNCEzJNy71UkeF4XIx2EVmL9KLwDQdmM=
+github.com/srwiley/rasterx v0.0.0-20200120212402-85cb7272f5e9/go.mod h1:mvWM0+15UqyrFKqdRjY6LuAVJR0HOVhJlEgZ5JWtSWU=
 github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -210,12 +237,16 @@ github.com/txn2/txeh v1.3.0/go.mod h1:O7M6gUTPeMF+vsa4c4Ipx3JDkOYrruB1Wry8QRsMcw
 github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
 github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
 github.com/urfave/cli v1.22.5/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
-github.com/urfave/cli/v2 v2.6.0 h1:yj2Drkflh8X/zUrkWlWlUjZYHyWN7WMmpVxyxXIUyv8=
-github.com/urfave/cli/v2 v2.6.0/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs=
+github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
+github.com/urfave/cli/v2 v2.5.1 h1:YKwdkyA0xTBzOaP2G0DVxBnCheHGP+Y9VbKAs4K1Ess=
+github.com/urfave/cli/v2 v2.5.1/go.mod h1:oDzoM7pVwz6wHn5ogWgFUU1s4VJayeQS+aEZDqXIEJs=
 github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
 github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
 github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c h1:3lbZUMbMiGUW/LMkfsEABsc5zNT9+b1CvsJx47JzJ8g=
 github.com/xtgo/uuid v0.0.0-20140804021211-a0b114877d4c/go.mod h1:UrdRz5enIKZ63MEE3IF9l2/ebyx59GyGgPi+tICQdmM=
+github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
+github.com/yuin/goldmark v1.3.8 h1:Nw158Q8QN+CPgTmVRByhVwapp8Mm1e2blinhmx4wx5E=
+github.com/yuin/goldmark v1.3.8/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
 go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
 go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
@@ -224,14 +255,18 @@ golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnf
 golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
 golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 golang.org/x/crypto v0.0.0-20211108221036-ceb1ce70b4fa/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220208050332-20e1d8d225ab/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
 golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
+golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
 golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
 golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -240,9 +275,11 @@ golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73r
 golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 golang.org/x/net v0.0.0-20200425230154-ff2c4b7c35a0/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
 golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
 golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
+golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211111083644-e5c967477495/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
 golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -255,6 +292,7 @@ golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4Iltr
 golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
 golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@@ -265,12 +303,17 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h
 golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20200720211630-cb9d2d5c5666/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
+golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -293,6 +336,10 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
 golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
 golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -316,6 +363,7 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
 gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
@@ -326,6 +374,8 @@ gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
 gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
 gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
+gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=

+ 33 - 0
netclient/gui/components/buttons.go

@@ -0,0 +1,33 @@
+package components
+
+import (
+	"image/color"
+
+	"fyne.io/fyne/v2"
+	"fyne.io/fyne/v2/canvas"
+	"fyne.io/fyne/v2/container"
+	"fyne.io/fyne/v2/layout"
+	"fyne.io/fyne/v2/widget"
+)
+
+// ColoredButton - renders a colored button with text
+func ColoredButton(text string, tapped func(), color color.Color) *fyne.Container {
+	btn := widget.NewButton(text, tapped)
+	bgColor := canvas.NewRectangle(color)
+	return container.New(
+		layout.NewMaxLayout(),
+		bgColor,
+		btn,
+	)
+}
+
+// ColoredIconButton - renders a colored button with an icon
+func ColoredIconButton(text string, icon fyne.Resource, tapped func(), color color.Color) *fyne.Container {
+	btn := widget.NewButtonWithIcon(text, icon, tapped)
+	bgColor := canvas.NewRectangle(color)
+	return container.New(
+		layout.NewMaxLayout(),
+		bgColor,
+		btn,
+	)
+}

+ 22 - 0
netclient/gui/components/colors.go

@@ -0,0 +1,22 @@
+package components
+
+import "image/color"
+
+var (
+	// Red_color - preferred red color
+	Red_color = color.NRGBA{R: 233, G: 10, B: 17, A: 155}
+	// Gravitl_color - gravitl primary sea green color
+	Gravitl_color = color.NRGBA{R: 14, G: 173, B: 105, A: 155}
+	// Blue_color - preferred blue color
+	Blue_color = color.NRGBA{R: 17, G: 157, B: 164, A: 155}
+	// Danger_color - preferred danger color
+	Danger_color = color.NRGBA{R: 223, G: 71, B: 89, A: 155}
+	// Purple_color - preferred purple color
+	Purple_color = color.NRGBA{R: 115, G: 80, B: 159, A: 155}
+	// Orange_color - preferred orange color
+	Orange_color = color.NRGBA{R: 253, G: 76, B: 65, A: 155}
+	// Grey_color - preferred grey color
+	Grey_color = color.NRGBA{R: 27, G: 27, B: 27, A: 155}
+	// Gold_color - preferred gold color
+	Gold_color = color.NRGBA{R: 218, G: 165, B: 32, A: 155}
+)

+ 22 - 0
netclient/gui/components/text.go

@@ -0,0 +1,22 @@
+package components
+
+import (
+	"image/color"
+
+	"fyne.io/fyne/v2"
+	"fyne.io/fyne/v2/canvas"
+	"fyne.io/fyne/v2/container"
+	"fyne.io/fyne/v2/layout"
+	"fyne.io/fyne/v2/widget"
+)
+
+// ColoredText - renders a colored label
+func ColoredText(text string, color color.Color) *fyne.Container {
+	btn := widget.NewLabel(text)
+	bgColor := canvas.NewRectangle(color)
+	return container.New(
+		layout.NewMaxLayout(),
+		bgColor,
+		btn,
+	)
+}

+ 39 - 0
netclient/gui/components/toolbar.go

@@ -0,0 +1,39 @@
+package components
+
+import (
+	"image/color"
+
+	"fyne.io/fyne/v2"
+	"fyne.io/fyne/v2/container"
+	"fyne.io/fyne/v2/widget"
+)
+
+// NewToolbarLabelButton - makes a toolbar button cell with label
+func NewToolbarLabelButton(label string, icon fyne.Resource, onclick func(), colour color.Color) widget.ToolbarItem {
+	l := ColoredIconButton(label, icon, onclick, colour)
+	l.MinSize()
+	return &toolbarLabelButton{l}
+}
+
+// NewToolbarLabel - makes a toolbar text cell
+func NewToolbarLabel(label string) widget.ToolbarItem {
+	l := widget.NewLabel(label)
+	l.MinSize()
+	return &toolbarLabel{l}
+}
+
+type toolbarLabelButton struct {
+	*fyne.Container
+}
+
+type toolbarLabel struct {
+	*widget.Label
+}
+
+func (t *toolbarLabelButton) ToolbarObject() fyne.CanvasObject {
+	return container.NewCenter(t.Container)
+}
+
+func (t *toolbarLabel) ToolbarObject() fyne.CanvasObject {
+	return container.NewCenter(t.Label)
+}

+ 21 - 0
netclient/gui/components/views/confirm.go

@@ -0,0 +1,21 @@
+package views
+
+import (
+	"fyne.io/fyne/v2"
+	"fyne.io/fyne/v2/container"
+	"fyne.io/fyne/v2/theme"
+	"fyne.io/fyne/v2/widget"
+	"github.com/gravitl/netmaker/netclient/gui/components"
+)
+
+// GetConfirmation - displays a confirmation message
+func GetConfirmation(msg string, onCancel, onConfirm func()) fyne.CanvasObject {
+	return container.NewGridWithColumns(1,
+		container.NewCenter(widget.NewLabel(msg)),
+		container.NewCenter(
+			container.NewHBox(
+				components.ColoredIconButton("Confirm", theme.ConfirmIcon(), onConfirm, components.Gravitl_color),
+				components.ColoredIconButton("Cancel", theme.CancelIcon(), onCancel, components.Danger_color),
+			)),
+	)
+}

+ 25 - 0
netclient/gui/components/views/content.go

@@ -0,0 +1,25 @@
+package views
+
+import (
+	"fyne.io/fyne/v2"
+)
+
+// CurrentContent - the content currently being displayed
+var CurrentContent *fyne.Container
+
+// RemoveContent - removes a rendered content
+func RemoveContent(name string) {
+	CurrentContent.Remove(GetView(name))
+}
+
+// AddContent - adds content to be rendered
+func AddContent(name string) {
+	CurrentContent.Add(GetView(name))
+}
+
+// RefreshComponent - refreshes the component to re-render
+func RefreshComponent(name string, c fyne.CanvasObject) {
+	RemoveContent(name)
+	SetView(name, c)
+	AddContent(name)
+}

+ 38 - 0
netclient/gui/components/views/join.go

@@ -0,0 +1,38 @@
+package views
+
+import (
+	"fmt"
+	"time"
+
+	"fyne.io/fyne/v2"
+	"fyne.io/fyne/v2/container"
+	"fyne.io/fyne/v2/theme"
+	"fyne.io/fyne/v2/widget"
+	"github.com/gravitl/netmaker/netclient/gui/components"
+)
+
+// GetJoinView - get's the join screen where a user inputs an access token
+func GetJoinView() fyne.CanvasObject {
+
+	input := widget.NewMultiLineEntry()
+	input.SetPlaceHolder("access token here...")
+
+	submitBtn := components.ColoredIconButton("Submit", theme.UploadIcon(), func() {
+		fmt.Printf("got text %s \n", input.Text)
+		// ErrorNotify("Could not process token")
+		LoadingNotify()
+		time.Sleep(time.Second)
+		SuccessNotify("Joined!")
+		// TODO
+		// - call join
+		// - display loading
+		// - on error display error notification
+		// - on success notify success, refresh networks & networks view, display networks view
+	}, components.Blue_color)
+
+	return container.NewGridWithColumns(1,
+		container.NewCenter(widget.NewLabel("Join new network with Access Token")),
+		input,
+		container.NewCenter(submitBtn),
+	)
+}

+ 117 - 0
netclient/gui/components/views/networks.go

@@ -0,0 +1,117 @@
+package views
+
+import (
+	"fmt"
+	"time"
+
+	"fyne.io/fyne/v2"
+	"fyne.io/fyne/v2/container"
+	"fyne.io/fyne/v2/layout"
+	"fyne.io/fyne/v2/theme"
+	"fyne.io/fyne/v2/widget"
+	"github.com/gravitl/netmaker/netclient/functions"
+	"github.com/gravitl/netmaker/netclient/gui/components"
+)
+
+var currentNetwork *string
+
+// GetNetworksView - displays the view of all networks
+func GetNetworksView(networks []string) fyne.CanvasObject {
+	// renders := []fyne.CanvasObject{}
+	if networks == nil || len(networks) == 0 {
+		return container.NewCenter(widget.NewLabel("No networks present"))
+	}
+	grid := container.New(layout.NewGridLayout(4),
+		container.NewCenter(widget.NewLabel("Network Name")),
+		container.NewCenter(widget.NewLabel("Node Info")),
+		container.NewCenter(widget.NewLabel("Pull Latest")),
+		container.NewCenter(widget.NewLabel("Leave network")),
+	)
+	for i := range networks {
+		network := &networks[i]
+		grid.AddObject(
+			container.NewCenter(widget.NewLabel(*network)),
+		)
+		grid.AddObject(
+			components.ColoredIconButton("info", theme.InfoIcon(), func() {
+				RefreshComponent(NetDetails, GetSingleNetworkView(*network))
+				ShowView(NetDetails)
+			}, components.Gold_color),
+		)
+		grid.AddObject(
+			components.ColoredIconButton("pull", theme.DownloadIcon(), func() {
+				// TODO call pull with network name
+				pull(*network)
+			}, components.Blue_color),
+		)
+		grid.AddObject(
+			components.ColoredIconButton("leave", theme.DeleteIcon(), func() {
+				leave(*network)
+			}, components.Danger_color),
+		)
+		// renders = append(renders, container.NewCenter(netToolbar))
+	}
+
+	return container.NewCenter(grid)
+}
+
+const fakeData = `{"networks":[{"name":"devops","node_id":"5aeb3e18-1236-46d8-8415-8699bfe5d44e","current_node":{"name":"ingress","interface":"nm-devops","private_ipv4":"10.10.10.1","public_endpoint":"167.71.106.39"},"peers":[{"public_key":"QlLJlQKy6C7XirHdnkXiMcCSCed2ieDt6qL3DSzjSxo=","public_endpoint":"167.71.100.69:51821","addresses":[{"cidr":"10.10.10.3/32","ip":"10.10.10.3"},{"cidr":"10.10.10.0/24","ip":"10.10.10.0"}]},{"public_key":"WnU5t2Rl9kD7lzASe8nH7VyS+jhTLUCigMJKKt+UrnU=","public_endpoint":"167.71.98.164:51821","addresses":[{"cidr":"10.10.10.2/32","ip":"10.10.10.2"},{"cidr":"165.227.116.94/32","ip":"165.227.116.94"}]},{"public_key":"rRI9qNHIiSQsIyZgGBvyZML98bZ6z8iZYfZLWPSZJ1k=","public_endpoint":"167.71.100.25:51821","addresses":[{"cidr":"10.10.10.5/32","ip":"10.10.10.5"}]},{"public_key":"R7JoXHCj9q/yXizr9q7p3xW5dxAX+l6Hg17k/98T0GI=","public_endpoint":"167.71.164.7:51821","addresses":[{"cidr":"10.10.10.254/32","ip":"10.10.10.254"}]},{"public_key":"M5gwhvr1Qrg55gGrPrkd3NbLJoDqTsjiEPvvf1yyaiQ=","public_endpoint":"\u003cnil\u003e","addresses":[{"cidr":"10.10.10.6/32","ip":"10.10.10.6"}]}]}]}`
+
+// GetSingleNetworkView - returns details and option to pull a network
+func GetSingleNetworkView(network string) fyne.CanvasObject {
+	if network == "" || len(network) == 0 {
+		return container.NewCenter(widget.NewLabel("No valid network selected"))
+	}
+	nodeID := "somenodeid"
+	health := "healthy"
+	privateAddr := "10.10.10.10"
+	privateAddr6 := "23:23:23:23"
+	endpoint := "182.3.4.4:55555"
+
+	pullBtn := components.ColoredButton("pull "+network, func() { pull(network) }, components.Blue_color)
+	pullBtn.Resize(fyne.NewSize(pullBtn.Size().Width, 50))
+	LoadingNotify()
+	time.Sleep(time.Second)
+	netDetailsView := container.NewCenter(
+		// components.ColoredText("Selected "+network, components.Orange_color),
+		container.NewGridWithColumns(1, widget.NewRichTextFromMarkdown(fmt.Sprintf(`### %s
+- ID: %s
+- Health: %s
+- Endpoint: %s
+- Address (IPv4): %s
+- Address6 (IPv6): %s
+`, network, nodeID, health, endpoint, privateAddr, privateAddr6)),
+			container.NewCenter(pullBtn),
+		))
+	ClearNotification()
+	return netDetailsView
+}
+
+// == private ==
+func pull(network string) {
+	LoadingNotify()
+	_, err := functions.Pull(network, true)
+	if err != nil {
+		ErrorNotify("Failed to pull " + network + " : " + err.Error())
+	} else {
+		SuccessNotify("Pulled " + network + "!")
+	}
+}
+
+func leave(network string) {
+
+	confirmView := GetConfirmation("Confirm leaving "+network+"?", func() {
+		ShowView(Networks)
+	}, func() {
+		LoadingNotify()
+		err := functions.LeaveNetwork(network, true)
+		if err != nil {
+			ErrorNotify("Failed to leave " + network + " : " + err.Error())
+		} else {
+			SuccessNotify("Left " + network)
+		}
+		ShowView(Networks)
+	})
+	RefreshComponent(Confirm, confirmView)
+	ShowView(Confirm)
+}

+ 39 - 0
netclient/gui/components/views/notification.go

@@ -0,0 +1,39 @@
+package views
+
+import (
+	"image/color"
+
+	"fyne.io/fyne/v2"
+	"fyne.io/fyne/v2/container"
+	"github.com/gravitl/netmaker/netclient/gui/components"
+)
+
+// GenerateNotification - generates a notification
+func GenerateNotification(text string, c color.Color) fyne.CanvasObject {
+	return container.NewCenter(components.ColoredText(text, c))
+}
+
+// ChangeNotification - changes the current notification in the view
+func ChangeNotification(text string, c color.Color) {
+	RefreshComponent(Notify, GenerateNotification(text, c))
+}
+
+// ClearNotification - hides the notifications
+func ClearNotification() {
+	RefreshComponent(Notify, GenerateNotification("", color.Transparent))
+}
+
+// LoadingNotify - changes notification to loading...
+func LoadingNotify() {
+	RefreshComponent(Notify, GenerateNotification("loading...", components.Blue_color))
+}
+
+// ErrorNotify - changes notification to a specified error
+func ErrorNotify(msg string) {
+	RefreshComponent(Notify, GenerateNotification(msg, components.Danger_color))
+}
+
+// SuccessNotify - changes notification to a specified success message
+func SuccessNotify(msg string) {
+	RefreshComponent(Notify, GenerateNotification(msg, components.Gravitl_color))
+}

+ 44 - 0
netclient/gui/components/views/state.go

@@ -0,0 +1,44 @@
+package views
+
+import (
+	"fyne.io/fyne/v2"
+)
+
+var (
+	// Views - the map of all the view components
+	views = make(map[string]fyne.CanvasObject)
+)
+
+const (
+	Networks   = "networks"
+	NetDetails = "netdetails"
+	Notify     = "notification"
+	Join       = "join"
+	Confirm    = "confirm"
+)
+
+// GetView - returns the requested view and sets the CurrentView state
+func GetView(viewName string) fyne.CanvasObject {
+	return views[viewName]
+}
+
+// SetView - sets a view in the views map
+func SetView(viewName string, component fyne.CanvasObject) {
+	views[viewName] = component
+}
+
+// HideView - hides a specific view
+func HideView(viewName string) {
+	views[viewName].Hide()
+}
+
+// ShowView - show's a specific view
+func ShowView(viewName string) {
+	for k := range views {
+		if k == Notify {
+			continue
+		}
+		HideView(k)
+	}
+	views[viewName].Show()
+}

+ 98 - 0
netclient/gui/gui.go

@@ -0,0 +1,98 @@
+package gui
+
+import (
+	"embed"
+	"image/color"
+	"time"
+
+	"fyne.io/fyne/v2"
+	"fyne.io/fyne/v2/app"
+	"fyne.io/fyne/v2/container"
+	"fyne.io/fyne/v2/theme"
+	"fyne.io/fyne/v2/widget"
+	"github.com/gravitl/netmaker/netclient/functions"
+	"github.com/gravitl/netmaker/netclient/gui/components"
+	"github.com/gravitl/netmaker/netclient/gui/components/views"
+)
+
+//go:embed nm-logo-sm.png
+var logoContent embed.FS
+
+func run(networks []string) error {
+	a := app.New()
+	window := a.NewWindow("Netclient")
+
+	img, err := logoContent.ReadFile("nm-logo.png")
+	if err != nil {
+		return err
+	}
+
+	window.SetIcon(&fyne.StaticResource{StaticName: "Netmaker logo", StaticContent: img})
+	window.Resize(fyne.NewSize(600, 400))
+
+	networkView := container.NewVScroll(views.GetNetworksView(networks))
+	networkView.SetMinSize(fyne.NewSize(400, 300))
+	views.SetView(views.Networks, networkView)
+
+	netDetailsViews := container.NewVScroll(views.GetSingleNetworkView(""))
+	netDetailsViews.SetMinSize(fyne.NewSize(400, 300))
+	views.SetView(views.NetDetails, netDetailsViews)
+	window.SetFixedSize(true)
+
+	toolbar := container.NewCenter(widget.NewToolbar(
+		components.NewToolbarLabelButton("Networks", theme.HomeIcon(), func() {
+			views.ShowView(views.Networks)
+			views.ClearNotification()
+		}, components.Blue_color),
+		components.NewToolbarLabelButton("Join new", theme.ContentAddIcon(), func() {
+			views.ShowView(views.Join)
+		}, components.Gravitl_color),
+		components.NewToolbarLabelButton("Uninstall", theme.ErrorIcon(), func() {
+			confirmView := views.GetConfirmation("Confirm Netclient uninstall?", func() {
+				views.ShowView(views.Networks)
+			}, func() {
+				views.LoadingNotify()
+				err := functions.Uninstall()
+				time.Sleep(time.Second >> 1)
+				if err != nil {
+					views.ErrorNotify("Failed to uninstall: \n" + err.Error())
+				} else {
+					views.SuccessNotify("Uninstalled Netclient!")
+				}
+				time.Sleep(time.Second >> 1)
+				views.ShowView(views.Networks)
+			})
+			views.RefreshComponent(views.Confirm, confirmView)
+			views.ShowView(views.Confirm)
+			// TODO:
+			// - call uninstall
+			// - Refresh networks view when finished
+		}, components.Red_color),
+	))
+
+	joinView := views.GetJoinView()
+	views.SetView(views.Join, joinView)
+
+	confirmView := views.GetConfirmation("", func() {}, func() {})
+	views.SetView(views.Confirm, confirmView)
+
+	views.ShowView(views.Networks)
+
+	initialNotification := views.GenerateNotification("", color.Transparent)
+	views.SetView(views.Notify, initialNotification)
+
+	views.CurrentContent = container.NewVBox()
+
+	views.CurrentContent.Add(container.NewGridWithRows(
+		1,
+		toolbar,
+	))
+	views.CurrentContent.Add(views.GetView(views.Networks))
+	views.CurrentContent.Add(views.GetView(views.NetDetails))
+	views.CurrentContent.Add(views.GetView(views.Notify))
+	views.CurrentContent.Add(views.GetView(views.Join))
+
+	window.SetContent(views.CurrentContent)
+	window.ShowAndRun()
+	return nil
+}

BIN
netclient/gui/nm-logo-sm.png