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.
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.
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.
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.
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)
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
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.
- 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
- 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
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.
Auto-generated by wails generate module. The FlexString custom type
produces unconventional namespace names in the generated TypeScript but
does not affect runtime behavior.
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.
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.
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.
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.
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.
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
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
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.
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.
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.
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.
Add configurable sort functionality to AniList watchlist system:
- Add aniListSort writable store to GlobalVariablesAndHelperFunctions
- Update Pagination component to subscribe to and use dynamic sort parameter
- Refactor CheckIfAniListLoggedInAndLoadWatchList to use sort from store
- Remove hardcoded MediaListSort.UpdatedTimeDesc in favor of configurable sort
- Improve code formatting with arrow functions and consistent spacing
- Add sort parameter to all GetAniListUserWatchingList calls
This allows users to customize their watchlist sorting preference instead of being limited to the default 'updated time descending' sort order.
- Convert from 4-space to 2-space indentation for consistency
- Improve import statement formatting and alignment
- Fix semicolon usage throughout the component
- Add conditional avatar dot indicator: green when all services (AniList, MAL, Simkl) are logged in, yellow otherwise
- Add missing newline at end of file
- General code style improvements for better readability and consistency with project standards
- Disable decrement button when on first page (page <= 1)
- Disable increment button when on last page (page >= lastPage)
- Prevents users from triggering invalid page navigation requests
- Improves UX by providing visual feedback for boundary conditions
This change prevents unnecessary API calls and improves user experience by clearly indicating when navigation bounds have been reached. The buttons will now be disabled at the appropriate boundaries, matching the behavior already present in the numbered page navigation section.
- Add proper type annotations to changePage function parameter using KeyboardEvent with HTMLInputElement currentTarget
- Add proper type annotations to changeCountPerPage function parameter using Event with HTMLSelectElement currentTarget
- Replace all e.target references with e.currentTarget to access properly typed DOM elements
- Add hover state styling to active page button for better UI feedback
This change resolves TypeScript errors where EventTarget type didn't have access to element-specific properties like 'value'. Using currentTarget instead of target provides the correct type since currentTarget refers to the element that has the event listener attached, ensuring type-safe access to input and select element properties.
- Update indentation from 4-space to 2-space convention throughout the component
- Reformat import statements to follow consistent spacing and alignment
- Standardize function and variable declarations with proper spacing
- Improve code readability with consistent formatting across all elements
- Clean up HTML template structure with proper indentation
- Add newline at end of file for standards compliance
This change ensures the Pagination component follows the project's code style conventions and improves maintainability through consistent formatting.
- Add explicit width (230px) and height (330px) to media cover images
- Apply object-cover class to maintain aspect ratio and prevent distortion
- Ensures uniform sizing across all media cover images in the watch list
This change improves visual consistency in the UI by standardizing the display dimensions of anime/manga cover images.
- Disable decrement button when progress is at 0 or below to prevent negative values
- Disable increment button when:
* Media has defined episodes and progress is complete (>= total episodes)
* Or when progress has reached next airing episode boundary (nextAiringEpisode - 2)
- Improves user experience by preventing invalid progress adjustments
- Maintains data integrity by stopping users from setting impossible progress values
Fixed TypeScript compilation error caused by import statement and function declaration being on the same line.
Changes:
- Separated import statement and onMount declaration onto different lines
- Resolved svelte-preprocess type error
- File now compiles correctly
This was a typo from previous commit where the loc import line was incorrectly merged with the existing onMount function declaration.
Removed the .vscode/extensions.json file from the frontend directory.
This file contained workspace-level VSCode extension recommendations which are better managed:
- At user level through personal VSCode settings
- Through project README documentation
- Via devcontainer or editors preferences if needed
Cleanup reduces repository clutter and avoids imposing specific extension recommendations on contributors.