Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7a875f84a5 | ||
|
|
a6e74ec808 | ||
|
|
2717137270 | ||
|
|
58ae55e061 | ||
|
|
eebb6906c6 | ||
|
|
0179d614b9 | ||
|
|
2794adaa21 | ||
|
|
37266ab8d4 | ||
|
|
74f5761e06 | ||
|
|
546234eacf | ||
|
|
7a822e8eaf | ||
|
|
b07f92853d | ||
|
|
3bb74eb672 | ||
|
|
8cf0f84ddc | ||
|
|
006b43a590 | ||
|
|
120b0c2647 | ||
|
|
a3702a900c | ||
|
|
ede81d551c | ||
|
|
7c19abb6ae | ||
|
|
8f93dde120 | ||
|
|
ca7b82dab5 | ||
|
|
fce8df9e84 | ||
|
|
1597f99eef | ||
|
|
9ad48ff310 | ||
|
|
af0ec78eae | ||
|
|
5f95df147f | ||
|
|
98cd855349 | ||
|
|
1aa14f9fd5 | ||
|
|
39cdd5e6c1 | ||
|
|
9bbefbcea8 | ||
|
|
9593e7c041 | ||
|
|
82aa2abfbd | ||
|
|
58c7165ce5 | ||
|
|
5bcf0eda0b | ||
|
|
0bfb140dc7 | ||
|
|
7b63799f0b | ||
|
|
a97c42323c | ||
|
|
fc0ed5ac2c | ||
|
|
69994d9856 | ||
|
|
843687ff2b | ||
|
|
7416aa37e0 | ||
|
|
ce83000e0c | ||
|
|
359e8ed63e | ||
|
|
3b9df94cf6 | ||
|
|
634f451595 | ||
|
|
00d7945f70 | ||
|
|
60d6a287e5 | ||
|
|
d5981b7475 | ||
|
|
523722bae6 | ||
|
|
71e6a58fbd | ||
|
|
a7e90e4ae5 | ||
|
|
654ab8b618 | ||
|
|
7a201808e3 | ||
|
|
77e4e444d4 | ||
|
|
bf1685a382 | ||
|
|
0ac43946b1 | ||
|
|
15ff7a20db | ||
|
|
1dd3f09fed | ||
|
|
87bdbc440a | ||
|
|
62b5a9db72 | ||
|
|
39156af48a | ||
|
|
3f40d3da29 | ||
|
|
a7a49f7441 | ||
|
|
e026e777f6 | ||
|
|
09a809c102 | ||
|
|
29ef37e237 | ||
|
|
713cb24508 | ||
|
|
589101c292 | ||
|
|
f807565cb2 | ||
|
|
6626d35920 | ||
|
|
5c76729a6b | ||
|
|
c260b8b231 | ||
|
|
971147dcb8 | ||
|
|
777df725b6 | ||
|
|
6cb8771994 | ||
|
|
ac013e7969 | ||
|
|
067a74e157 | ||
|
|
1dcd55d5ff | ||
|
|
e87369912d | ||
|
|
63bb323ac3 | ||
|
|
e7054741a0 | ||
|
|
70d51aef47 | ||
|
|
519e7bcf25 | ||
|
|
4d69d95c88 | ||
|
|
c0e330ea22 |
@@ -0,0 +1,15 @@
|
||||
# Contributing
|
||||
|
||||
As you might have gathered, this Gitea instance does not allow registrations. If you want to have an account on this instance in order to contribute to this project, you must contact me for an account. I am available on:
|
||||
|
||||
- XMPP: `x@sunglocto.net`
|
||||
- Matrix: `@x:sunglocto.net`
|
||||
- E-Mail: sunglocto <img width=16px height=16px src="https://sunglocto.net/icons/email.gif"/> protonmail.com
|
||||
|
||||
For actually submitting your patches, you can just fork this repo and submit a pull request. I currently have no contribution policy that you have to follow however if you just use common sense you should be good.
|
||||
|
||||
## AI contributions
|
||||
|
||||
Obviously vibe-coded or fully AI-generated contributions will be immediately rejected. This is in order to ensure the stability of the project and decrease the chance of significant bugs or vulnerabilities.
|
||||
|
||||
AI contributions that you have reviewed, edited and **ensured that they compile, run and work successfully** are acceptable. AI is a tool, and like any other tools, can be used for good if used in moderation.
|
||||
@@ -1,12 +1,11 @@
|
||||
# lambda
|
||||
|
||||
In order to run this program you must have a file named `lambda.toml` that specifies your config.
|
||||
Here is an example:
|
||||
an XMPP client
|
||||
|
||||
```toml
|
||||
Server = "example.com:5222"
|
||||
Username = "user@example.com"
|
||||
Password = "123456789"
|
||||
Insecure = false
|
||||
Nick = "User"
|
||||
```
|
||||
Experimental XMPP client written in Go, with the GTK4 UI toolkit and the Fluux IO XMPP libraries.
|
||||
|
||||
icons are from Psi+ ([https://github.com/psi-im](https://github.com/psi-im))
|
||||
|
||||
additional icons are by Mark James's Silk Icon Set [https://github.com/markjames/famfamfam-silk-icons](https://github.com/markjames/famfamfam-silk-icons) and the [Haiku project](https://www.haiku-os.org/)
|
||||
|
||||
pepper & carrot default avatar is from [Pepper&Carrot](https://peppercarrot.com) - created by David Revoy, licensed under Creative Commons Attribution 4.0. Change made: cropped and made black & white
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
# TODO
|
||||
- XEP-0393: Message Styling 0%
|
||||
- XEP-0402: PEP Native Bookmarks 0%
|
||||
- XEP-0066: Out of Band Data partial
|
||||
- XEP-0461: Message Replies partial
|
||||
- XEP-0461: Message Replies 0%
|
||||
- XEP-0444: Message Reactions partial
|
||||
|
||||
|
||||
@@ -0,0 +1,306 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
_ "embed"
|
||||
"github.com/diamondburned/gotk4/pkg/gdk/v4"
|
||||
"github.com/diamondburned/gotk4/pkg/gdkpixbuf/v2"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// If you want to change the default profile picture used when Identicons are disabled, you can change the below line to an image in the repository and recompile Lambda.
|
||||
|
||||
//go:embed debug_psi.png
|
||||
var defaultAvatarBytes []byte
|
||||
|
||||
//go:embed failed_load.png
|
||||
var failedBytes []byte
|
||||
|
||||
//go:embed assets/owner.png
|
||||
var ownerMedalBytes []byte
|
||||
|
||||
//go:embed assets/admin.png
|
||||
var adminMedalBytes []byte
|
||||
|
||||
//go:embed assets/member.png
|
||||
var memberMedalBytes []byte
|
||||
|
||||
//go:embed assets/noaffiliation.png
|
||||
var noneMedalBytes []byte
|
||||
|
||||
//go:embed assets/outcast.png
|
||||
var outcastMedalBytes []byte
|
||||
|
||||
//go:embed assets/cancel.png
|
||||
var cancelBytes []byte
|
||||
|
||||
//go:embed assets/status_away.png
|
||||
var sABytes []byte
|
||||
|
||||
//go:embed assets/status_busy.png
|
||||
var sBBytes []byte
|
||||
|
||||
//go:embed assets/status_chatty.png
|
||||
var sCBytes []byte
|
||||
|
||||
//go:embed assets/status_online.png
|
||||
var sOBytes []byte
|
||||
|
||||
//go:embed assets/status_xa.png
|
||||
var xaBytes []byte
|
||||
|
||||
//go:embed assets/tag.png
|
||||
var tagBytes []byte
|
||||
|
||||
//go:embed assets/lambda-disabled.png
|
||||
var logoDisabledBytes []byte
|
||||
|
||||
//go:embed assets/icon.png
|
||||
var logoBytes []byte
|
||||
|
||||
//go:embed assets/group.png
|
||||
var groupBytes []byte
|
||||
|
||||
//go:embed assets/door_in.png
|
||||
var doorInBytes []byte
|
||||
|
||||
//go:embed assets/door_out.png
|
||||
var doorOutBytes []byte
|
||||
|
||||
//go:embed assets/large_group.png
|
||||
var largeGroupBytes []byte
|
||||
|
||||
//go:embed assets/world.png
|
||||
var worldBytes []byte
|
||||
|
||||
//go:embed assets/disconnect.png
|
||||
var disconnectBytes []byte
|
||||
|
||||
//go:embed assets/chart_bar.png
|
||||
var barBytes []byte
|
||||
|
||||
//go:embed assets/chart_bar_laggy.png
|
||||
var barLaggyBytes []byte
|
||||
|
||||
//go:embed assets/ok.png
|
||||
var okBytes []byte
|
||||
|
||||
//go:embed assets/hourglass.png
|
||||
var hourglassBytes []byte
|
||||
|
||||
//go:embed assets/connect_tls.png
|
||||
var connectBytes []byte
|
||||
|
||||
//go:embed assets/comment.png
|
||||
var commentBytes []byte
|
||||
|
||||
//go:embed assets/information.png
|
||||
var informationBytes []byte
|
||||
|
||||
//go:embed assets/car.png
|
||||
var carBytes []byte
|
||||
|
||||
//go:embed assets/car_high.png
|
||||
var carHighBytes []byte
|
||||
|
||||
// muc icons
|
||||
|
||||
//go:embed assets/muc_open.png
|
||||
var mucOpenBytes []byte
|
||||
|
||||
//go:embed assets/muc_membersonly.png
|
||||
var mucMembersOnlyBytes []byte
|
||||
|
||||
//go:embed assets/muc_passwordprotected.png
|
||||
var mucPasswordProtectedBytes []byte
|
||||
|
||||
//go:embed assets/muc_unsecured.png
|
||||
var mucUnsecuredBytes []byte
|
||||
|
||||
//go:embed assets/muc_hidden.png
|
||||
var mucHiddenBytes []byte
|
||||
|
||||
//go:embed assets/muc_public.png
|
||||
var mucPublicBytes []byte
|
||||
|
||||
//go:embed assets/muc_unmoderated.png
|
||||
var mucUnmoderatedBytes []byte
|
||||
|
||||
//go:embed assets/muc_moderated.png
|
||||
var mucModeratedBytes []byte
|
||||
|
||||
//go:embed assets/muc_nonanonymous.png
|
||||
var mucNonAnonymousBytes []byte
|
||||
|
||||
//go:embed assets/muc_semianonymous.png
|
||||
var mucSemiAnonymousBytes []byte
|
||||
|
||||
//go:embed assets/muc_persistent.png
|
||||
var mucPersistentBytes []byte
|
||||
|
||||
//go:embed assets/muc_temporary.png
|
||||
var mucTemporaryBytes []byte
|
||||
|
||||
//go:embed assets/moderate.png
|
||||
var moderateBytes []byte
|
||||
|
||||
//go:embed assets/jabber.png
|
||||
var jabberBytes []byte
|
||||
|
||||
//go:embed assets/fail.png
|
||||
var failBytes []byte
|
||||
|
||||
//go:embed assets/please_wait.gif
|
||||
var pleaseWaitBytes []byte
|
||||
|
||||
//go:embed assets/update.png
|
||||
var updateBytes []byte
|
||||
|
||||
//go:embed assets/solar.png
|
||||
var solarBytes []byte
|
||||
|
||||
//go:embed assets/timeline_marker.png
|
||||
var timelineMarkerBytes []byte
|
||||
|
||||
//go:embed assets/cap.png
|
||||
var capIconBytes []byte
|
||||
|
||||
// client icons
|
||||
|
||||
//go:embed assets/client_icons/monocles.png
|
||||
var monoclesCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/gajim.png
|
||||
var gajimCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/conversations.png
|
||||
var conversationsCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/dino.png
|
||||
var dinoCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/blabber.png
|
||||
var blabberCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/profanity.png
|
||||
var profanityCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/poezio.png
|
||||
var poezioCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/mcabber.png
|
||||
var mcabberCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/converse.png
|
||||
var converseJSCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/pidgin.png
|
||||
var pidginCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/anotherim.png
|
||||
var anotherImCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/movim.png
|
||||
var movimCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/yaxim.png
|
||||
var yaximCapBytes []byte
|
||||
|
||||
//go:embed assets/client_icons/psi.png
|
||||
var psiCapBytes []byte
|
||||
|
||||
var clientAssets sync.Map
|
||||
|
||||
func loadAsset(key string, data []byte) {
|
||||
loader := gdkpixbuf.NewPixbufLoader()
|
||||
loader.Write(data)
|
||||
loader.Close()
|
||||
clientAssets.Store(key, gdk.NewTextureForPixbuf(loader.Pixbuf()))
|
||||
}
|
||||
|
||||
func clientAssetsLoad(key string) gdk.Paintabler {
|
||||
dat, ok := clientAssets.Load(key)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
paintable, ok := dat.(gdk.Paintabler)
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return paintable
|
||||
}
|
||||
|
||||
func init() {
|
||||
for key, data := range map[string][]byte{
|
||||
"logo": logoBytes,
|
||||
"DefaultAvatar": defaultAvatarBytes,
|
||||
"FailedAvatar": failedBytes,
|
||||
"owner": ownerMedalBytes,
|
||||
"admin": adminMedalBytes,
|
||||
"member": memberMedalBytes,
|
||||
"none": noneMedalBytes,
|
||||
"outcast": outcastMedalBytes,
|
||||
"cancel": cancelBytes,
|
||||
"tag": tagBytes,
|
||||
"disabled_logo": logoDisabledBytes,
|
||||
"group": groupBytes,
|
||||
"door_in": doorInBytes,
|
||||
"door_out": doorOutBytes,
|
||||
"large_group": largeGroupBytes,
|
||||
"world": worldBytes,
|
||||
"disconnect": disconnectBytes,
|
||||
"chart_bar": barBytes,
|
||||
"chart_bar_laggy": barLaggyBytes,
|
||||
"ok": okBytes,
|
||||
"hourglass": hourglassBytes,
|
||||
"connect": connectBytes,
|
||||
"comment": commentBytes,
|
||||
"information": informationBytes,
|
||||
"status_away": sABytes,
|
||||
"status_dnd": sBBytes,
|
||||
"status_chat": sCBytes,
|
||||
"status_xa": xaBytes,
|
||||
"status_": sOBytes,
|
||||
"car": carBytes,
|
||||
"car_high": carHighBytes,
|
||||
"muc_open": mucOpenBytes,
|
||||
"muc_membersonly": mucMembersOnlyBytes,
|
||||
"muc_passwordprotected": mucPasswordProtectedBytes,
|
||||
"muc_unsecured": mucUnsecuredBytes,
|
||||
"muc_hidden": mucHiddenBytes,
|
||||
"muc_public": mucPublicBytes,
|
||||
"muc_unmoderated": mucUnmoderatedBytes,
|
||||
"muc_moderated": mucModeratedBytes,
|
||||
"muc_nonanonymous": mucNonAnonymousBytes,
|
||||
"muc_semianonymous": mucSemiAnonymousBytes,
|
||||
"muc_persistent": mucPersistentBytes,
|
||||
"muc_temporary": mucTemporaryBytes,
|
||||
"moderate": moderateBytes,
|
||||
"jabber": jabberBytes,
|
||||
"fail": failBytes,
|
||||
"please_wait": pleaseWaitBytes,
|
||||
"update": updateBytes,
|
||||
"solar": solarBytes,
|
||||
"timeline_marker": timelineMarkerBytes,
|
||||
"cap": capIconBytes,
|
||||
|
||||
"https://monocles.eu": monoclesCapBytes,
|
||||
"https://gajim.org": gajimCapBytes,
|
||||
"http://conversations.im": conversationsCapBytes,
|
||||
"https://dino.im": dinoCapBytes,
|
||||
"http://blabber.im": blabberCapBytes,
|
||||
"http://profanity-im.github.io": profanityCapBytes,
|
||||
"https://poez.io": poezioCapBytes,
|
||||
"http://mcabber.com/caps": mcabberCapBytes,
|
||||
"https://conversejs.org": converseJSCapBytes,
|
||||
"http://pidgin.im/": pidginCapBytes,
|
||||
"https://dev.narayana.im/narayana/Conversations-Classic": anotherImCapBytes,
|
||||
"https://movim.eu/": movimCapBytes,
|
||||
"https://yaxim.org/": yaximCapBytes,
|
||||
"https://psi-im.org": psiCapBytes,
|
||||
} {
|
||||
loadAsset(key, data)
|
||||
}
|
||||
|
||||
}
|
||||
|
After Width: | Height: | Size: 600 B |
|
After Width: | Height: | Size: 762 B |
|
After Width: | Height: | Size: 226 KiB |
|
After Width: | Height: | Size: 607 B |
|
After Width: | Height: | Size: 287 B |
|
After Width: | Height: | Size: 671 B |
|
After Width: | Height: | Size: 656 B |
|
After Width: | Height: | Size: 456 B |
|
After Width: | Height: | Size: 641 B |
|
After Width: | Height: | Size: 541 B |
|
After Width: | Height: | Size: 434 B |
@@ -0,0 +1 @@
|
||||
All client assets are owned by their respective owners
|
||||
|
After Width: | Height: | Size: 783 B |
|
After Width: | Height: | Size: 196 B |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 246 B |
|
After Width: | Height: | Size: 551 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 5.1 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.6 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 362 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 1.4 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 588 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 1.8 KiB |
|
After Width: | Height: | Size: 263 B |
|
After Width: | Height: | Size: 1.3 KiB |
|
After Width: | Height: | Size: 413 B |
|
After Width: | Height: | Size: 721 B |
|
After Width: | Height: | Size: 796 B |
|
After Width: | Height: | Size: 693 B |
|
After Width: | Height: | Size: 643 B |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 753 B |
|
After Width: | Height: | Size: 744 B |
|
After Width: | Height: | Size: 264 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 778 B |
|
After Width: | Height: | Size: 730 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 747 B |
|
After Width: | Height: | Size: 597 B |
|
After Width: | Height: | Size: 793 B |
|
After Width: | Height: | Size: 593 B |
|
After Width: | Height: | Size: 935 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 970 B |
|
After Width: | Height: | Size: 508 B |
|
After Width: | Height: | Size: 612 B |
|
After Width: | Height: | Size: 806 B |
|
After Width: | Height: | Size: 622 B |
|
After Width: | Height: | Size: 924 B |
|
After Width: | Height: | Size: 882 B |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 903 B |
|
After Width: | Height: | Size: 591 B |
|
After Width: | Height: | Size: 460 B |
|
After Width: | Height: | Size: 538 B |
|
After Width: | Height: | Size: 584 B |
|
After Width: | Height: | Size: 88 KiB |
|
After Width: | Height: | Size: 543 B |
|
After Width: | Height: | Size: 794 B |
|
After Width: | Height: | Size: 751 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 722 B |
|
After Width: | Height: | Size: 1.1 KiB |
|
After Width: | Height: | Size: 910 B |
|
After Width: | Height: | Size: 327 B |
|
After Width: | Height: | Size: 3.0 KiB |
|
After Width: | Height: | Size: 362 B |
|
After Width: | Height: | Size: 923 B |
@@ -5,6 +5,7 @@ package main
|
||||
|
||||
import (
|
||||
"crypto/sha256"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/diamondburned/gotk4/pkg/gdk/v4"
|
||||
"github.com/diamondburned/gotk4/pkg/gtk/v4"
|
||||
@@ -13,10 +14,17 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// global or app-level map/cache
|
||||
var textureCache = make(map[string]gdk.Paintabler)
|
||||
// var textureCache = make(map[string]gdk.Paintabler)
|
||||
var textureCache sync.Map
|
||||
|
||||
// Invalid images, if an image/avatar cannot be loaded on the system (e.g: incompatible format) it's put here
|
||||
// var invalidImages = make(map[string]bool)
|
||||
|
||||
var invalidImages sync.Map
|
||||
|
||||
func ensureCache() (string, error) {
|
||||
cachePath := configdir.LocalCache("lambda-im")
|
||||
@@ -28,49 +36,70 @@ func ensureCache() (string, error) {
|
||||
return cachePath, nil
|
||||
}
|
||||
|
||||
func getTexture(path string) gdk.Paintabler {
|
||||
if tex, exists := textureCache[path]; exists {
|
||||
return tex
|
||||
func getTexture(path string) (gdk.Paintabler, error) {
|
||||
tex, exists := textureCache.Load(path)
|
||||
if exists {
|
||||
return tex.(gdk.Paintabler), nil
|
||||
}
|
||||
|
||||
tex, err := gdk.NewTextureFromFilename(path) // load once
|
||||
if err != nil {
|
||||
panic(err)
|
||||
return nil, err
|
||||
}
|
||||
textureCache[path] = tex
|
||||
return tex
|
||||
textureCache.Store(path, tex)
|
||||
t, ok := tex.(gdk.Paintabler)
|
||||
if !ok {
|
||||
return nil, errors.New("invalid type")
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
|
||||
func newPictureFromPath(path string) *gtk.Picture {
|
||||
tex := getTexture(path)
|
||||
func newPictureFromPath(path string) (*gtk.Picture, error) {
|
||||
tex, err := getTexture(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
img := gtk.NewPictureForPaintable(tex)
|
||||
return img
|
||||
return img, nil
|
||||
}
|
||||
|
||||
func newImageFromPath(path string) *gtk.Image {
|
||||
tex := getTexture(path)
|
||||
img := gtk.NewImageFromPaintable(tex)
|
||||
return img
|
||||
func newImageFromPath(path string) (*gtk.Image, error) {
|
||||
tex, err := getTexture(path)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return gtk.NewImageFromPaintable(tex), nil
|
||||
}
|
||||
|
||||
func newPictureFromWeb(url string) *gtk.Picture {
|
||||
func setImageFromPath(path string, i *gtk.Image) error {
|
||||
tex, err := getTexture(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
i.SetFromPaintable(tex)
|
||||
return nil
|
||||
}
|
||||
|
||||
func newPictureFromWeb(url string) (*gtk.Picture, error) {
|
||||
pa, _ := ensureCache()
|
||||
// step 1: get a sha256 sum of the URL
|
||||
sum := fmt.Sprintf("%x", sha256.Sum256([]byte(url)))
|
||||
|
||||
p, ok := textureCache[sum]
|
||||
p, ok := textureCache.Load(sum)
|
||||
if ok {
|
||||
return gtk.NewPictureForPaintable(p)
|
||||
return gtk.NewPictureForPaintable(p.(gdk.Paintabler)), nil
|
||||
}
|
||||
|
||||
// step 2: download it
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fullpath := filepath.Join(pa, sum)
|
||||
@@ -78,31 +107,31 @@ func newPictureFromWeb(url string) *gtk.Picture {
|
||||
// step 3: save it
|
||||
err = os.WriteFile(fullpath, b, 0644)
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newPictureFromPath(fullpath)
|
||||
}
|
||||
|
||||
func newImageFromWeb(url string) *gtk.Image {
|
||||
func newImageFromWeb(url string) (*gtk.Image, error) {
|
||||
pa, _ := ensureCache()
|
||||
// step 1: get a sha256 sum of the URL
|
||||
sum := fmt.Sprintf("%x", sha256.Sum256([]byte(url)))
|
||||
|
||||
p, ok := textureCache[sum]
|
||||
p, ok := textureCache.Load(sum)
|
||||
if ok {
|
||||
return gtk.NewImageFromPaintable(p)
|
||||
return gtk.NewImageFromPaintable(p.(gdk.Paintabler)), nil
|
||||
}
|
||||
|
||||
// step 2: download it
|
||||
resp, err := http.Get(url)
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fullpath := filepath.Join(pa, sum)
|
||||
@@ -110,7 +139,7 @@ func newImageFromWeb(url string) *gtk.Image {
|
||||
// step 3: save it
|
||||
err = os.WriteFile(fullpath, b, 0644)
|
||||
if err != nil {
|
||||
return nil
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return newImageFromPath(fullpath)
|
||||
|
||||
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |