Commit Graph
307 Commits
Author SHA1 Message Date
John O'Keefe 336a1f353f chore(release): bump version to 1.6.8
Release / release (push) Canceled after 20s
1.6.8
2026-09-12 21:27:12 -04:00
John O'Keefe a19080ef39 Revert "docs: add Wails v3 + Android migration plan"
The migration plan belongs to the wailsv3 branch, not main. It was merged forward into wailsv3 (now at origin/wailsv3) before this revert, so no content is lost. Main keeps only the v2 keyring error-handling fix.
2026-09-12 21:26:25 -04:00
John O'Keefe 2bddc6a224 docs: add Wails v3 + Android migration plan
Skimmable phased plan for getting AniTrack onto Android for personal
sideload use (no Play Store, no official F-Droid). Written for both the
maintainer and as working context for AI-assisted implementation.

Covers: desktop v3 parity as a mechanical step (main.go, runtime call
mapping, wailsjs import rewrite), per-file Android storage shims
(keyring on desktop vs EncryptedSharedPreferences via
Android.Secure*), the localhost :6734 to anitrack:// deep-link OAuth
redesign with per-provider dashboard changes, and the sideload run/
package commands plus Obtainium updates. Includes guardrails: small
diffs, per-service file ownership, build-tagged platform files only,
runnable check per phase, and open decisions (first provider, desktop
parallel builds, redirect URI registration).
2026-09-12 21:23:14 -04:00
John O'Keefe 3bf5d8290e fix(auth): handle keyring open/set errors per service
Stop ignoring keyring.Open failures in all three login files. A failed
Open previously left a nil ring behind the blank identifier, so the next
Get/Set panicked with no message. Each service now opens its ring in
init, logs a service-prefixed warning when storage is unavailable, and
guards every use with a Ready check that fails safe to logged-out.

- AniListUserFunctions.go: add aniRingReady/aniRingSet helpers, log
  Open and per-key Set failures, reject invalid ExpiresIn instead of
  silently storing 0, clear in-memory JWT on logout even when storage
  is missing
- MALUserFunctions.go: add malRingReady/malRingSet helpers covering
  login, OAuth callback, and token-refresh saves; same Open/Set/
  ExpiresIn/logout treatment
- SimklUserFunctions.go: add simklRingReady/simklRingSet helpers;
  same Open/Set/logout treatment

No wallet, key names, or login flow changed. Same ServiceName
AniTrack, same keys, same OAuth callback behavior.
2026-09-12 21:22:58 -04:00
John O'Keefe a5da544dd7 chore(release): bump version to 1.6.7
Release / release (push) Successful in 11m52s
1.6.7
2026-09-11 16:22:45 -04:00
John O'Keefe 270faeb507 feat(ci): automate Linux release builds and Gitea releases
Release / release (push) Successful in 13m50s
Local flow is now ./release 1.6.7 (or make release VERSION=1.6.7):
bump wails.json productVersion, commit the bump, generate git-cliff
notes into an annotated plain-version tag, and push commit plus tag.
The tag push fires the new Gitea Actions workflow.

- cliff.toml: git-cliff groups matching Bookhoard, tag_pattern for
  plain versions so --latest scopes correctly.
- Makefile release target: strict plain-semver validation, dirty-tree
  and existing-tag guards, python3 wails.json bump committed as
  chore(release), throwaway-tag notes generation, push of main + tag.
- release: wrapper normalizing v/AniTrack- prefixes to plain versions.
- .gitea/workflows/release.yml: version guard (wails.json vs tag,
  base-match for -suffix pre-releases), Go 1.25 / Node 20 / Wails
  v2.15.0 + webkit2_41 system deps, environment.go from Actions
  secrets, make build, AniTrack-<version>.tar.gz packaged from
  build/ (bin, icon, desktop, install script, README), idempotent
  Release create/update named AniTrack-<version> with archive
  attached via REGISTRY_TOKEN PAT.
1.6.6-secrets-test
2026-09-11 16:00:37 -04:00
John O'Keefe abba1803fc chore(release): bump version to 1.6.6
Update productVersion in wails.json from 1.6.5 to 1.6.6 to accompany
the MAL token variable fix and the authenticated AniList search fix.
2026-09-11 15:23:43 -04:00
John O'Keefe ce35a20eba fix(anilist): send auth token on search when logged in
AniListSearch hardcoded false for the authenticated flag to
AniListQuery, forcing anonymous searches even with a valid AniList
session. Pass a.CheckIfAniListLoggedIn() instead so the stored token
is attached when available, enabling user-specific data and
authenticated rate limits while keeping anonymous search as fallback.
2026-09-11 15:23:40 -04:00
John O'Keefe e5ce250392 fix(mal): correct swapped access and refresh token variables
In CheckIfMyAnimeListLoggedIn and MyAnimeListLogin the keyring lookups
assigned MyAnimeListAccessToken to refreshToken and
MyAnimeListRefreshToken to accessToken. Downstream code checks
len(accessToken.Data) for login state and assigns
accessToken.Data -> myAnimeListJwt.AccessToken, so the swap gated
login on the refresh token and stored each token in the wrong field.

Swap the variable names to match their keyring keys so login detection,
JWT restoration, and the empty-token fallback in MyAnimeListLogin use
the correct values.
2026-09-11 15:23:29 -04:00
john-okeefe 0cca48adb1 chore(release): bump version to 1.6.5 1.6.5 2026-09-03 19:12:18 -04:00
john-okeefe d2f2f8a618 fix(ui): make header search states explicit with slow-day timeouts
The search dropdown toggled blindly before the async call settled
and only handled success, so API failures left a blank dropdown
that looked like search did nothing.

- Replace toggle with explicit open/close, Escape and outside-click
  to dismiss, and disabled search button while a request is in flight
- Add isSearching/searchError/hasSearched states: loading text,
  failure panel with message plus Retry, empty prompt, and a
  no-results message for the searched term
- Guard null coverImage/title with a romaji/native fallback and a
  keyed each block; ignore stale late responses via request ids
- Tolerate slow AniList days: slow notice at 8s, 30s Promise.race
  fail-safe (backend allows 20s), and an immediate offline message
  via navigator.onLine so the UI never spins indefinitely
2026-09-03 19:09:44 -04:00
john-okeefe fcbcda7eac fix(anilist): harden AniList query transport and search errors
AniListQuery previously ignored json.Marshal/http.NewRequest errors,
logged the wrong variable on client.Do failure, and dereferenced a
nil response body, which could panic and leave callers hanging.

- Return early with user-safe messages on encode/request failures
- Add 20s http.Client timeout and nil guards for res/res.Body
- Keep logs generic so no auth material is ever printed
- Add aniListGraphQLErrorMessage/aniListSearchStatusError helpers
  mapping 429 to a rate-limit retry message, 5xx to a temporary
  outage message, and GraphQL errors[] (even on HTTP 200) to a
  surfaced message
- AniListSearch rejects empty bodies and unparseable payloads with
  actionable errors instead of failing silently downstream
2026-09-03 19:09:40 -04:00
john-okeefe 0a89ec3652 fix(anilist): decode array-shaped airingSchedule/relations and isolate per-service sync errors
The 1.6.1 fix exposed a latent decoding bug: AniList returns
airingSchedule.nodes and relations.nodes as arrays, but the Go Media
struct declared Nodes as single structs. Every full-media response
failed json.Unmarshal partway through - the update path turned that
into a rejected promise which skipped the MAL and Simkl syncs and all
table updates, while page loads silently continued with partially
decoded data (the reason the old tags/genres copy workaround existed).

- Media.AiringSchedule.Nodes is now []AiringScheduleNode and
  Media.Relations is an exported []MediaRelation (previously an
  unexported field silently dropped by encoding/json); title and
  fuzzy-date sub-structs promoted to named types.
- Regenerate wailsjs models for the new shapes.
- Anime.svelte: handleSubmit and deleteEntries now wrap each service
  in its own try/catch surfaced via setApiError/ErrorModal, so one
  service failing can no longer skip the others; removed the obsolete
  tags/genres copy workaround.
- AniListUpdateEntry/AniListDeleteEntry log HTTP status and response
  body on failure for terminal diagnostics.

Bump productVersion to 1.6.2.
1.6.2
2026-09-01 20:18:42 -04:00
john-okeefe 5a14863a8f fix(anilist): repair SaveMediaListEntry mutation and surface update failures
The AniListUpdateEntry mutation was mangled in 54c109a when the
standardized media field block was pasted in without the media { }
wrapper: media-level fields (idMal, title, ...) sat directly on
SaveMediaListEntry (which returns MediaList), the MediaList fields
(status, startedAt, ..., user) ended up at the Mutation root, and a
stray closing brace made the document a guaranteed 400. Because the
response status was discarded, the frontend received a zeroed
AniListGetSingleAnime and blanked the anime page after every submit,
making AniList appear logged out (and the change was never saved).

- Restore the mutation to match the tested bruno request: id/mediaId/
  userId, standard media block inside media { }, MediaList fields
  inside the selection, balanced braces.
- AniListUpdateEntry and AniListDeleteEntry now return an error on
  403/non-200/unparseable responses (mirroring
  GetAniListUserWatchingList) instead of silently returning zero
  values.
- Anime.svelte guards against replacing the page data with an empty
  response and raises the API error modal instead.

Bump productVersion to 1.6.1.
2026-09-01 19:49:47 -04:00
john-okeefe a16c804692 feat(ui): show per-service login status while accounts are being checked
When the app starts it verifies all three services sequentially, which
could leave the other two login controls looking idle or trigger login
actions before their real state is known. Track which service is
currently being checked and reflect it in the header:

- Add a serviceLoggingIn store (plus setServiceLoggingIn and
  isServiceLoggingIn helpers) to GlobalVariablesAndHelperFunctions.
- Have the loginTo* functions and the startup CheckIf* functions toggle
  their service in the store (seed all three at startup, clear each as
  it resolves).
- In Header, the login buttons show a spinner with 'Checking AniList' /
  'Checking MAL' / 'Checking Simkl' and are disabled while that service
  is being checked, reverting to the normal 'AniList Login' style label
  once its state is known.
- In the avatar menu, the 'Login to X' row shows a spinner with the
  matching 'Checking X' text while that service is logging in.
1.6.0
2026-08-29 13:13:42 -04:00
john-okeefe d08756c36f fix(mal): distinguish silent token refresh from a fresh re-login
Two MAL login issues were caused by the refresh path being conflated
with the full browser OAuth flow:

1. A spurious 'It is now safe to close your browser tab' dialog was
   shown after a *silent* background token refresh, even though the
   browser was never opened. The dialog now belongs only to the
   browser-callback handler (handleMyAnimeListCallback); the refresh
   raises no dialog.

2. When both the access token and the refresh token were invalid, the
   app reported MAL as logged in without a username. Now, if a refresh
   fails (HttpClient error, non-2xx, or an empty access token), the
   stale tokens are cleared and a fresh browser OAuth login is
   automatically initiated instead of silently returning an empty user.

refreshMyAnimeListAuthorizationToken now returns a bool indicating
whether a fresh access token was actually obtained, letting
GetMyAnimeListLoggedInUser decide between retrying with the refreshed
token or falling back to a full re-login.
2026-08-29 13:13:37 -04:00
john-okeefe b42456f255 chore(gitignore): ignore build binaries and archive artifacts
Ignore compiled binaries and packaging archives that are generated
during a build, without hiding tracked build source files:

- build/bin: the compiled application binary
- *.tar / *.tar.gz: packaging archives (e.g. Wails .ptmp temp dirs)
- /AniTrack: the root app binary (fix the previous './AniTrack'
  pattern, which gitignore did not match)
2026-08-29 13:13:25 -04:00
john-okeefe 49ac5bef03 chore(wailsjs): regenerate Go bindings for the AniList Browse feature
Re-run the Wails binding generator so the frontend reflects the browse
Go types that were added in earlier commits (AniListBrowse plus the
Media / MediaList model refinements):

- App.d.ts / App.js: expose the new AniListBrowse() method
- models.ts: add the Media model, the anonymous tags element type,
  and type MediaList.media as Media instead of a generic object
2026-08-29 13:12:22 -04:00
john-okeefe b9f4c12839 chore(deps): upgrade Wails to v2.15.0 and bump golang.org/x dependencies
Reinstall the Go toolchain and rebuild wails against v2.15.0, then run
'go mod tidy' to update the dependency graph:

- github.com/wailsapp/wails/v2  v2.12.0 -> v2.15.0
- golang.org/x/crypto  v0.52.0 -> v0.53.0
- golang.org/x/net     v0.55.0 -> v0.56.0
- golang.org/x/sys     v0.45.0 -> v0.46.0
- golang.org/x/term    v0.43.0 -> v0.44.0
- golang.org/x/text    v0.37.0 -> v0.39.0

The regenerated Wails runtime bindings (runtime.d.ts / runtime.js) are
included as they surface new APIs shipped in v2.15: the cross-platform
notification API (InitializeNotifications, SendNotification, etc.) and
the EventsOffAll event helper.
2026-08-29 13:12:18 -04:00
john-okeefe 54c109ae3b rewrote standard media call and added browse function 2026-07-22 15:22:58 -04:00
john-okeefe d3bc93f6c9 tested for standardizing media call 2026-07-22 15:22:38 -04:00
john-okeefe 0384f570c5 added AniList Browse Fetch for new feature 2026-07-21 16:53:25 -04:00
john-okeefe 6925cd4e08 fixed gitignore to just ignore the Anitrack binary at root 2026-07-21 16:52:47 -04:00
john-okeefe 23960e0613 chore: upgrade Go to 1.25 and update dependencies
- Bump Go toolchain from 1.24.0 to 1.25.0
- Upgrade Wails from v2.10.1 to v2.12.0
- Upgrade tidwall/gjson from v1.18.0 to v1.19.0
- Upgrade labstack/echo from v4.13.3 to v4.15.2
- Upgrade labstack/gommon from v0.4.2 to v0.5.0
- Upgrade samber/lo from v1.49.1 to v1.53.0
- Upgrade gorilla/websocket to v1.5.3 (new transitive dep)
- Upgrade go-webview2 from v1.0.19 to v1.0.23
- Upgrade danieljoos/wincred from v1.2.2 to v1.2.3
- Upgrade godbus/dbus/v5 from v5.1.0 to v5.2.2
- Upgrade jchv/go-winloader to latest
- Upgrade mattn/go-isatty from v0.0.20 to v0.0.22
- Upgrade tidwall/match from v1.1.1 to v1.2.0
- Upgrade golang.org/x/crypto, net, sys, term to latest
- Add go-toast/v2 as new transitive dependency from Wails
1.5.5
2026-05-27 20:17:09 -04:00
john-okeefe 669b41c62c chore: bump version to 1.5.5 2026-05-27 20:02:16 -04:00
john-okeefe c54a11e7bd fix(build): improve Linux install script reliability and idempotency
- Fix tilde expansion: replace quoted '~' paths with $HOME so they
  actually resolve to the user's home directory instead of being
  treated literally
- Add existence checks before copying files so the script is
  idempotent and skips already-installed resources
- Add progress/status echo messages for each installation step
  so the user can see what is being done
2026-05-27 20:01:39 -04:00
john-okeefe b6bdee4df6 chore: bump version to 1.5.1 2026-05-27 17:41:27 -04:00
john-okeefe cbda217d18 chore: add compiled AniTrack binary to .gitignore
The project's compiled binary (AniTrack) was not covered by existing
gitignore patterns. Only platform-specific extensions like .exe, .dll,
.so, and .dylib were ignored. Add the bare binary name to prevent the
locally-built executable from appearing as an untracked file.
2026-05-27 17:41:19 -04:00
john-okeefe ceb756a1a8 chore: regenerate Wails TypeScript models for FlexString type
Auto-generated by wails generate module. The FlexString custom type
produces unconventional namespace names in the generated TypeScript but
does not affect runtime behavior.
2026-05-27 17:36:05 -04:00
john-okeefe 3621b66437 fix: handle MAL API returning numbers instead of strings for zero-value statistics
The MyAnimeList API inconsistently returns statistics status fields (watching,
completed, on_hold, dropped, plan_to_watch) as quoted strings for non-zero
values (e.g. "8217") but as bare numbers for zero values (e.g. 0). This caused
JSON unmarshal errors for anime with zero counts in any status field.

Introduce a FlexString custom type that implements json.Unmarshaler to accept
both JSON strings and JSON numbers, always storing the result as a string. The
type definition lives in MALTypes.go and the unmarshal logic in MALFunctions.go
to keep static types and behavior separate.
1.5.1
2026-05-27 17:28:54 -04:00
john-okeefe 7f92b1714e chore: bump version to 1.5.0
Update productVersion from 1.0.0 to 1.5.0 in Wails project
configuration to reflect the addition of AniList watchlist sorting,
extracted refresh button component, and pagination improvements.
1.5.0
2026-04-24 23:02:21 -04:00
john-okeefe cd142f7601 chore: remove release notes file 2026-04-24 23:01:29 -04:00
john-okeefe fe48e6a8c4 docs: add release notes for v1.0.0
Add comprehensive release notes documenting the first stable release of
AniTrack, including highlights such as webkit2gtk 4.1 Linux builds,
comprehensive error handling across all services, AniList watchlist
sorting, and various UI polish improvements.
2026-04-24 23:01:00 -04:00
john-okeefe 24d4d24edf fix(frontend): remove extraneous top margin from pagination controls
Remove the mt-5 class from the pagination container div to eliminate
unnecessary spacing between the pagination buttons and the per-page
selector.
2026-04-24 23:00:54 -04:00
john-okeefe b68abfc1c9 refactor(frontend): extract refresh button into standalone component and put sort dropdown in watchlist header
Move the refresh button out of the WatchList component header and into
its own RefreshWatchListButton.svelte component, placing it at the top
of the Home route page with right-alignment. This gives the refresh
control better visibility at the page level rather than being buried
inside the watchlist header.

Replace the removed refresh button in the WatchList header with the new
Sort dropdown component, giving users sort controls directly alongside
the watchlist title.
2026-04-24 23:00:50 -04:00
john-okeefe eadc96fb4f feat(frontend): add AniList watchlist sort dropdown component
Implement a Sort.svelte component that provides a dropdown menu allowing
users to dynamically reorder their AniList watchlist by various parameters
including media title, score, status, progress, popularity, and dates.

The component binds to the global aniListSort store and fetches updated
watchlist data from the backend whenever the user selects a new sort option,
providing immediate visual feedback.
2026-04-24 23:00:35 -04:00
john-okeefe 6a662cdf6e chore: bump version to 1.0.0
Update productVersion from 0.7.0 to 1.0.0 in Wails project
configuration to reflect the first major release milestone.
1.0.0
2026-04-24 19:39:08 -04:00
john-okeefe 2a9777872f chore: update author email address
Change contact email from jokeefe@fastmail.com to admin@linuxhg.com
in the Wails project configuration.
2026-04-24 19:38:56 -04:00
john-okeefe b03d4ab7e3 build: add Makefile with webkit2_41 build tag for Linux
Wails v2 defaults to linking against webkit2gtk-4.0, but modern Linux
distributions (e.g. Fedora) only ship webkit2gtk-4.1. The webkit2_41
build tag tells Wails to link against the correct library.

Provides two targets:
- make dev: run wails dev with the correct tag
- make build: build the production binary with the correct tag
- make clean: remove build artifacts
2026-04-24 17:10:29 -04:00
john-okeefe ff1b8fb742 chore: remove release notes for v0.6.5 2026-04-24 17:10:21 -04:00
john-okeefe cbd4c7cd01 docs: add release notes for v0.6.5
Add detailed release notes for the v0.6.5 patch release covering:
- Enhanced button disabled states in Anime and Pagination components
- Fixed media cover image sizing in WatchList
- AvatarMenu service status indicator
- TypeScript type safety fixes in Pagination event handlers
- Code formatting standardization across components
2026-04-24 17:10:03 -04:00
john-okeefe 335d757255 chore: remove release notes file
Release notes will be managed externally. Keeping repository focused on source code only.
2026-03-30 20:17:09 -04:00
john-okeefe a3b4857175 docs: add release notes for v0.7.0
Comprehensive release notes documenting:
- Major error handling improvements
- Backend API changes (AniList, MAL, Simkl)
- Frontend error modal and state management
- Bug fixes and stability improvements
- Technical details and upgrade instructions
0.7.0
2026-03-30 20:12:47 -04:00
john-okeefe 6e4b9c041a chore: remove vite timestamp file
Remove generated vite timestamp file that was accidentally tracked.
2026-03-30 20:08:39 -04:00
john-okeefe ae54fd20dd feat(frontend): integrate error handling into application
App.svelte:
- Import and render ErrorModal component
- Add ErrorModal to main app layout below Header

CheckIfAniListLoggedInAndLoadWatchList.svelte:
- Import error state helpers (setApiError, clearApiError)
- Wrap LoadAniListUser in try-catch with error handling
- Wrap LoadAniListWatchList in try-catch with error handling
- Update CheckIfAniListLoggedInAndLoadWatchList with error handling
- Remove old alert() calls in favor of modal system

Home.svelte:
- Import isApiDown and apiError stores
- Add conditional rendering for API down state
- Display user-friendly "API Unavailable" message when apiError is set
- Show warning icon and helpful messaging

Error handling is now fully integrated across the frontend application.
2026-03-30 20:08:34 -04:00
john-okeefe 2c7e2d0eff feat(frontend): add error modal component
Add new ErrorModal component for API error display:
- Auto-displays when apiError store is set
- Shows service name, error message, and status code
- Provides "Retry Connection" button to attempt reconnection
- Provides "Dismiss" button to close modal and continue
- Integrates with all three services (AniList, MAL, Simkl)
- Uses flowbite-svelte Modal and Button components
- Proper Svelte event handling with on:click

Uses Tailwind CSS for styling with red error theme and helpful messaging.
2026-03-30 20:08:29 -04:00
john-okeefe 9a9f055c38 feat(frontend): add API error state management
Add centralized error state system:
- New ApiError interface (service, message, statusCode, canRetry)
- apiError writable store for current error state
- isApiDown writable store for API availability status
- setApiError() helper to set error states
- clearApiError() helper to reset error states

Provides reactive error state across entire application.
2026-03-30 20:08:23 -04:00
john-okeefe bc497521e7 feat(simkl): add comprehensive error handling
SimklFunctions.go:
- Update SimklHelper to return (json.RawMessage, error)
- Add status code validation (200-299 range)
- Update SimklGetUserWatchlist to return (SimklWatchListType, error)
- Update SimklSyncEpisodes to return (SimklAnime, error)
- Update SimklSyncRating to return (SimklAnime, error)
- Update SimklSyncStatus to return (SimklAnime, error)
- Update SimklSearch to return (SimklAnime, error)
- Update SimklSyncRemove to return (bool, error)
- Add proper error wrapping for all failure scenarios

SimklUserFunctions.go:
- Replace log.Fatalf with log.Printf in server error handling (line 119)
- Replace log.Fatal with log.Printf in JSON marshaling (line 141)

All Simkl API calls now properly propagate errors to frontend.
2026-03-30 20:08:20 -04:00
john-okeefe 48a6005725 feat(mal): add comprehensive error handling
MALFunctions.go:
- Update MALHelper to return (json.RawMessage, string, error)
- Add network error handling and proper request error checking
- Update GetMyAnimeList to return (MALWatchlist, error)
- Update MyAnimeListUpdate to return (MalListStatus, error)
- Update GetMyAnimeListAnime to return (MALAnime, error)
- Update DeleteMyAnimeListEntry to return (bool, error)

MALUserFunctions.go:
- Replace log.Fatalf with log.Printf in server error handling
- Prevent server shutdown on OAuth callback errors

All MAL API calls now properly propagate errors to frontend.
2026-03-30 20:08:16 -04:00
john-okeefe 93a94d0797 chore: bump version to 0.7.0
Preparing release for comprehensive error handling improvements across all API integrations (AniList, MAL, Simkl).
2026-03-30 20:08:08 -04:00