diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 4fa36db..0000000 --- a/.npmrc +++ /dev/null @@ -1,5 +0,0 @@ -engine-strict=true - -# Optimize package installation -prefer-offline=true -audit=false \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 74539d8..bdb87e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.26.0](https://github.com/rodrigogs/whats-reader/compare/v1.25.1...v1.26.0) (2026-01-05) + + +### Features + +* Add responsive chat header options menu for small screens ([#55](https://github.com/rodrigogs/whats-reader/issues/55)) ([4932bd2](https://github.com/rodrigogs/whats-reader/commit/4932bd21ee0bfd552308e43b41e027e8f20ec6c5)), closes [#56](https://github.com/rodrigogs/whats-reader/issues/56) + ## [1.25.1](https://github.com/rodrigogs/whats-reader/compare/v1.25.0...v1.25.1) (2026-01-05) diff --git a/package-lock.json b/package-lock.json index 05fc3d5..1c59e7c 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "whats-reader", - "version": "1.25.1", + "version": "1.26.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "whats-reader", - "version": "1.25.1", + "version": "1.26.0", "license": "AGPL-3.0", "dependencies": { "@floating-ui/dom": "^1.7.4", diff --git a/package.json b/package.json index 852971b..7435e8e 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "whats-reader", "productName": "WhatsApp Backup Reader", - "version": "1.25.1", + "version": "1.26.0", "description": "A desktop app to read and visualize WhatsApp chat exports", "license": "AGPL-3.0", "author": { diff --git a/src/routes/+page.svelte b/src/routes/+page.svelte index 00d38d2..24ee59b 100644 --- a/src/routes/+page.svelte +++ b/src/routes/+page.svelte @@ -101,6 +101,8 @@ function closeParticipantsModal() { } let showPerspectiveDropdown = $state(false); let perspectiveSearchQuery = $state(''); +let showChatOptionsDropdown = $state(false); +let chatOptionsButtonRef = $state(null); // Loading chats state - shows placeholder items while importing interface LoadingChat { @@ -389,6 +391,7 @@ function selectPerspective(participant: string | null) { perspectiveByChat = newMap; } showPerspectiveDropdown = false; + showChatOptionsDropdown = false; perspectiveSearchQuery = ''; } @@ -587,6 +590,42 @@ const currentUser = $derived.by(() => { {#if appState.selectedChat} + {#snippet perspectiveSelectorContent()} + + + + + + {#if !perspectiveSearchQuery} + selectPerspective(null)} + > + {currentPerspective === null ? '✓' : ''} + {m.perspective_none()} + + {/if} + {#each filteredParticipants as participant} + selectPerspective(participant)} + > + {currentPerspective === participant ? '✓' : ''} + {participant} + + {/each} + {#if filteredParticipants.length === 0 && perspectiveSearchQuery} +
+ {m.perspective_no_match({ query: perspectiveSearchQuery })} +
+ {/if} +
+ {/snippet} +
@@ -628,90 +667,134 @@ const currentUser = $derived.by(() => {
- -
+ +
showPerspectiveDropdown = !showPerspectiveDropdown} - title={m.perspective_view_as()} - aria-label={m.perspective_select()} + onclick={() => showChatOptionsDropdown = !showChatOptionsDropdown} + title={m.chat_options()} + aria-label={m.chat_options()} > - + { showPerspectiveDropdown = false; perspectiveSearchQuery = ''; }} + anchor={chatOptionsButtonRef} + open={showChatOptionsDropdown} + onClose={() => { + showChatOptionsDropdown = false; + showPerspectiveDropdown = false; + perspectiveSearchQuery = ''; + }} + width="w-56" + placement="bottom-end" > - - - - - - {#if !perspectiveSearchQuery} + {#if showPerspectiveDropdown} + + {@render perspectiveSelectorContent()} + {:else} + + selectPerspective(null)} + active={!!currentPerspective} + onclick={() => showPerspectiveDropdown = true} > - {currentPerspective === null ? '✓' : ''} - {m.perspective_none()} + + {m.perspective_view_as()} - {/if} - {#each filteredParticipants as participant} selectPerspective(participant)} + active={showMediaGallery} + onclick={() => { + showChatOptionsDropdown = false; + toggleMediaGallery(); + }} > - {currentPerspective === participant ? '✓' : ''} - {participant} + + {m.media_gallery_title()} - {/each} - {#if filteredParticipants.length === 0 && perspectiveSearchQuery} -
- {m.perspective_no_match({ query: perspectiveSearchQuery })} -
- {/if} -
+ { + showChatOptionsDropdown = false; + toggleBookmarks(); + }} + > + + {m.bookmarks_title()} + + { + showChatOptionsDropdown = false; + toggleStats(); + }} + > + + {m.stats_view()} + +
+ {/if}
- - - - - - - - - + + + +