@peers-app/peers-ui 0.14.0 → 0.15.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/publish.yml +8 -5
- package/babel.config.js +4 -4
- package/biome.json +191 -0
- package/dist/command-palette/command-palette-ui.d.ts +1 -2
- package/dist/command-palette/command-palette-ui.js +175 -244
- package/dist/command-palette/command-palette.js +65 -64
- package/dist/components/chat-overlay.d.ts +2 -2
- package/dist/components/chat-overlay.js +160 -217
- package/dist/components/checkbox.d.ts +5 -4
- package/dist/components/checkbox.js +4 -7
- package/dist/components/group-switcher.d.ts +1 -2
- package/dist/components/group-switcher.js +119 -159
- package/dist/components/input-date.d.ts +3 -3
- package/dist/components/input-date.js +6 -6
- package/dist/components/input-number.d.ts +7 -6
- package/dist/components/input-number.js +25 -20
- package/dist/components/input.d.ts +5 -4
- package/dist/components/input.js +4 -7
- package/dist/components/inverse-lazy-list.d.ts +3 -3
- package/dist/components/inverse-lazy-list.js +13 -47
- package/dist/components/io-schema-values.d.ts +5 -6
- package/dist/components/io-schema-values.js +28 -65
- package/dist/components/io-schema.d.ts +4 -5
- package/dist/components/io-schema.js +42 -79
- package/dist/components/lazy-list.d.ts +3 -3
- package/dist/components/lazy-list.js +38 -58
- package/dist/components/list-screen.d.ts +3 -8
- package/dist/components/list-screen.js +28 -23
- package/dist/components/loading-indicator.d.ts +1 -2
- package/dist/components/loading-indicator.js +2 -6
- package/dist/components/markdown-editor/autolink-plugin.js +5 -8
- package/dist/components/markdown-editor/editor-inline.d.ts +2 -3
- package/dist/components/markdown-editor/editor-inline.js +2 -6
- package/dist/components/markdown-editor/editor.d.ts +6 -6
- package/dist/components/markdown-editor/editor.js +9 -19
- package/dist/components/markdown-editor/markdown-plugin.d.ts +1 -1
- package/dist/components/markdown-editor/markdown-plugin.js +20 -21
- package/dist/components/markdown-editor/mention-node.d.ts +2 -2
- package/dist/components/markdown-editor/mention-node.js +24 -24
- package/dist/components/markdown-editor/mentions-plugin.d.ts +2 -2
- package/dist/components/markdown-editor/mentions-plugin.js +61 -62
- package/dist/components/markdown-editor/theme.js +28 -28
- package/dist/components/markdown-editor/toolbar.d.ts +2 -3
- package/dist/components/markdown-editor/toolbar.js +32 -49
- package/dist/components/markdown-with-mentions.d.ts +1 -1
- package/dist/components/markdown-with-mentions.js +43 -43
- package/dist/components/message-logs/message-logs.d.ts +1 -2
- package/dist/components/message-logs/message-logs.js +91 -116
- package/dist/components/messages/avatar.d.ts +3 -4
- package/dist/components/messages/avatar.js +37 -46
- package/dist/components/messages/channel-message-list.d.ts +5 -6
- package/dist/components/messages/channel-message-list.js +34 -34
- package/dist/components/messages/channel-view.d.ts +1 -2
- package/dist/components/messages/channel-view.js +23 -57
- package/dist/components/messages/message-compose.d.ts +3 -4
- package/dist/components/messages/message-compose.js +27 -38
- package/dist/components/messages/message-display.d.ts +2 -3
- package/dist/components/messages/message-display.js +42 -95
- package/dist/components/messages/thread-message-list.d.ts +4 -5
- package/dist/components/messages/thread-message-list.js +29 -29
- package/dist/components/router.d.ts +1 -2
- package/dist/components/router.js +58 -66
- package/dist/components/save-button.d.ts +3 -3
- package/dist/components/save-button.js +23 -33
- package/dist/components/sortable-list.d.ts +11 -12
- package/dist/components/sortable-list.js +42 -22
- package/dist/components/tabs.d.ts +3 -3
- package/dist/components/tabs.js +16 -47
- package/dist/components/tooltip.d.ts +4 -4
- package/dist/components/tooltip.js +4 -9
- package/dist/components/trust-level-badge.d.ts +2 -3
- package/dist/components/trust-level-badge.js +16 -16
- package/dist/components/trust-level-dropdown.d.ts +3 -4
- package/dist/components/trust-level-dropdown.js +32 -55
- package/dist/components/typeahead.d.ts +3 -3
- package/dist/components/typeahead.js +48 -89
- package/dist/components/voice-indicator.d.ts +2 -2
- package/dist/components/voice-indicator.js +93 -106
- package/dist/components/voice-subscribe-events.d.ts +32 -0
- package/dist/components/voice-subscribe-events.js +2 -0
- package/dist/globals.d.ts +3 -5
- package/dist/globals.js +22 -33
- package/dist/hooks.d.ts +5 -5
- package/dist/hooks.js +22 -12
- package/dist/hooks.test.js +129 -145
- package/dist/index.d.ts +9 -8
- package/dist/index.js +13 -12
- package/dist/mention-configs.d.ts +2 -2
- package/dist/mention-configs.js +55 -42
- package/dist/screens/assistants/assistant-config.d.ts +2 -3
- package/dist/screens/assistants/assistant-config.js +9 -22
- package/dist/screens/assistants/assistant-details.d.ts +1 -2
- package/dist/screens/assistants/assistant-details.js +13 -28
- package/dist/screens/assistants/assistant-info.d.ts +2 -3
- package/dist/screens/assistants/assistant-info.js +3 -17
- package/dist/screens/assistants/assistant-list.d.ts +1 -2
- package/dist/screens/assistants/assistant-list.js +15 -56
- package/dist/screens/assistants/assistant-tools.d.ts +2 -3
- package/dist/screens/assistants/assistant-tools.js +10 -24
- package/dist/screens/console-logs/console-logs-list.d.ts +1 -2
- package/dist/screens/console-logs/console-logs-list.js +130 -134
- package/dist/screens/console-logs/log-display.d.ts +2 -3
- package/dist/screens/console-logs/log-display.js +40 -42
- package/dist/screens/console-logs/log-filters.d.ts +1 -2
- package/dist/screens/console-logs/log-filters.js +2 -24
- package/dist/screens/console-logs/mobile-log-card.d.ts +2 -3
- package/dist/screens/console-logs/mobile-log-card.js +64 -67
- package/dist/screens/console-logs/resizable-table-header.d.ts +1 -2
- package/dist/screens/console-logs/resizable-table-header.js +31 -67
- package/dist/screens/contacts/contact-details.d.ts +1 -2
- package/dist/screens/contacts/contact-details.js +16 -46
- package/dist/screens/contacts/contact-list.d.ts +1 -2
- package/dist/screens/contacts/contact-list.js +44 -103
- package/dist/screens/contacts/index.d.ts +4 -4
- package/dist/screens/contacts/index.js +1 -1
- package/dist/screens/contacts/user-connect.d.ts +1 -2
- package/dist/screens/contacts/user-connect.js +85 -186
- package/dist/screens/data-explorer/data-explorer.d.ts +1 -2
- package/dist/screens/data-explorer/data-explorer.js +61 -181
- package/dist/screens/data-explorer/index.d.ts +2 -2
- package/dist/screens/data-explorer/query-executor.d.ts +1 -2
- package/dist/screens/data-explorer/query-executor.js +56 -166
- package/dist/screens/groups/group-details.d.ts +1 -2
- package/dist/screens/groups/group-details.js +27 -122
- package/dist/screens/groups/group-invite-listener.d.ts +2 -3
- package/dist/screens/groups/group-invite-listener.js +8 -104
- package/dist/screens/groups/group-list.d.ts +1 -2
- package/dist/screens/groups/group-list.js +56 -133
- package/dist/screens/groups/group-members.d.ts +2 -3
- package/dist/screens/groups/group-members.js +62 -132
- package/dist/screens/groups/index.d.ts +4 -4
- package/dist/screens/groups/index.js +1 -1
- package/dist/screens/join-group/index.d.ts +2 -2
- package/dist/screens/join-group/join-group.d.ts +1 -2
- package/dist/screens/join-group/join-group.js +9 -109
- package/dist/screens/network-viewer/connection-troubleshooter.d.ts +2 -3
- package/dist/screens/network-viewer/connection-troubleshooter.js +89 -193
- package/dist/screens/network-viewer/cpu-usage-graph.d.ts +1 -2
- package/dist/screens/network-viewer/cpu-usage-graph.js +60 -99
- package/dist/screens/network-viewer/device-details-modal.d.ts +1 -2
- package/dist/screens/network-viewer/device-details-modal.js +25 -177
- package/dist/screens/network-viewer/group-details-modal.d.ts +1 -2
- package/dist/screens/network-viewer/group-details-modal.js +31 -142
- package/dist/screens/network-viewer/index.d.ts +4 -4
- package/dist/screens/network-viewer/index.js +3 -3
- package/dist/screens/network-viewer/network-viewer-ipc.d.ts +22 -0
- package/dist/screens/network-viewer/network-viewer-ipc.js +6 -0
- package/dist/screens/network-viewer/network-viewer.d.ts +1 -2
- package/dist/screens/network-viewer/network-viewer.js +91 -296
- package/dist/screens/network-viewer/usage-graph.d.ts +1 -2
- package/dist/screens/network-viewer/usage-graph.js +78 -110
- package/dist/screens/packages/package-details.d.ts +1 -2
- package/dist/screens/packages/package-details.js +35 -41
- package/dist/screens/packages/package-info.d.ts +2 -2
- package/dist/screens/packages/package-info.js +33 -86
- package/dist/screens/packages/package-list.d.ts +1 -2
- package/dist/screens/packages/package-list.js +42 -106
- package/dist/screens/packages/package-new-local.d.ts +1 -2
- package/dist/screens/packages/package-new-local.js +13 -19
- package/dist/screens/packages/package-versions.d.ts +2 -3
- package/dist/screens/packages/package-versions.js +29 -96
- package/dist/screens/peer-types/peer-type-details.d.ts +3 -4
- package/dist/screens/peer-types/peer-type-details.js +26 -78
- package/dist/screens/peer-types/peer-type-list.d.ts +1 -2
- package/dist/screens/peer-types/peer-type-list.js +13 -24
- package/dist/screens/search/global-search.d.ts +1 -2
- package/dist/screens/search/global-search.js +104 -182
- package/dist/screens/settings/color-mode-dropdown.d.ts +3 -4
- package/dist/screens/settings/color-mode-dropdown.js +18 -37
- package/dist/screens/settings/settings-page.d.ts +1 -1
- package/dist/screens/settings/settings-page.js +86 -213
- package/dist/screens/settings/voice-settings-agent.d.ts +1 -1
- package/dist/screens/settings/voice-settings-agent.js +7 -44
- package/dist/screens/settings/voice-settings-api-keys.d.ts +2 -2
- package/dist/screens/settings/voice-settings-api-keys.js +2 -29
- package/dist/screens/settings/voice-settings-output.d.ts +2 -2
- package/dist/screens/settings/voice-settings-output.js +2 -40
- package/dist/screens/settings/voice-settings-providers.d.ts +2 -2
- package/dist/screens/settings/voice-settings-providers.js +2 -19
- package/dist/screens/settings/voice-settings-types.d.ts +4 -4
- package/dist/screens/settings/voice-settings-types.js +31 -31
- package/dist/screens/settings/voice-settings-wake-word.d.ts +2 -2
- package/dist/screens/settings/voice-settings-wake-word.js +2 -33
- package/dist/screens/settings/voice-settings.d.ts +1 -1
- package/dist/screens/settings/voice-settings.js +35 -112
- package/dist/screens/setup-user.d.ts +1 -2
- package/dist/screens/setup-user.js +38 -116
- package/dist/screens/tools/tool-code.d.ts +2 -3
- package/dist/screens/tools/tool-code.js +9 -13
- package/dist/screens/tools/tool-details.d.ts +1 -2
- package/dist/screens/tools/tool-details.js +26 -39
- package/dist/screens/tools/tool-info.d.ts +2 -3
- package/dist/screens/tools/tool-info.js +9 -48
- package/dist/screens/tools/tool-list.d.ts +1 -2
- package/dist/screens/tools/tool-list.js +33 -65
- package/dist/screens/tools/tool-schema.d.ts +2 -3
- package/dist/screens/tools/tool-schema.js +2 -13
- package/dist/screens/tools/tool-test-details.d.ts +1 -2
- package/dist/screens/tools/tool-test-details.js +12 -28
- package/dist/screens/tools/tool-test-list.d.ts +1 -2
- package/dist/screens/tools/tool-test-list.js +17 -56
- package/dist/screens/variables/variable-details.d.ts +1 -2
- package/dist/screens/variables/variable-details.js +19 -86
- package/dist/screens/variables/variable-list.d.ts +1 -2
- package/dist/screens/variables/variable-list.js +16 -27
- package/dist/screens/welcome-modal.d.ts +1 -2
- package/dist/screens/welcome-modal.js +44 -111
- package/dist/screens/workflows/workflow-details.d.ts +1 -2
- package/dist/screens/workflows/workflow-details.js +17 -31
- package/dist/screens/workflows/workflow-info.d.ts +2 -3
- package/dist/screens/workflows/workflow-info.js +2 -9
- package/dist/screens/workflows/workflow-instructions.d.ts +2 -3
- package/dist/screens/workflows/workflow-instructions.js +23 -55
- package/dist/screens/workflows/workflow-list.d.ts +1 -2
- package/dist/screens/workflows/workflow-list.js +23 -62
- package/dist/setupTests.d.ts +1 -1
- package/dist/setupTests.js +10 -11
- package/dist/system-apps/assistants.app.d.ts +1 -1
- package/dist/system-apps/assistants.app.js +3 -3
- package/dist/system-apps/console-logs.app.d.ts +1 -1
- package/dist/system-apps/console-logs.app.js +3 -3
- package/dist/system-apps/contacts.app.d.ts +1 -1
- package/dist/system-apps/contacts.app.js +4 -4
- package/dist/system-apps/data-explorer.app.d.ts +1 -1
- package/dist/system-apps/data-explorer.app.js +4 -4
- package/dist/system-apps/groups.app.d.ts +1 -1
- package/dist/system-apps/groups.app.js +4 -4
- package/dist/system-apps/index.d.ts +17 -17
- package/dist/system-apps/index.js +52 -52
- package/dist/system-apps/join-group.app.d.ts +1 -1
- package/dist/system-apps/join-group.app.js +4 -4
- package/dist/system-apps/mobile-settings.app.d.ts +1 -1
- package/dist/system-apps/mobile-settings.app.js +3 -3
- package/dist/system-apps/network-viewer.app.d.ts +1 -1
- package/dist/system-apps/network-viewer.app.js +4 -4
- package/dist/system-apps/packages.app.d.ts +1 -1
- package/dist/system-apps/packages.app.js +3 -3
- package/dist/system-apps/search.app.d.ts +1 -1
- package/dist/system-apps/search.app.js +4 -4
- package/dist/system-apps/settings.app.d.ts +1 -1
- package/dist/system-apps/settings.app.js +3 -3
- package/dist/system-apps/threads.app.d.ts +1 -1
- package/dist/system-apps/threads.app.js +3 -3
- package/dist/system-apps/tools.app.d.ts +1 -1
- package/dist/system-apps/tools.app.js +3 -3
- package/dist/system-apps/types.app.d.ts +1 -1
- package/dist/system-apps/types.app.js +3 -3
- package/dist/system-apps/variables.app.d.ts +1 -1
- package/dist/system-apps/variables.app.js +3 -3
- package/dist/system-apps/workflows.app.d.ts +1 -1
- package/dist/system-apps/workflows.app.js +3 -3
- package/dist/tabs-layout/tabs-layout.d.ts +2 -3
- package/dist/tabs-layout/tabs-layout.js +215 -246
- package/dist/tabs-layout/tabs-state.d.ts +2 -2
- package/dist/tabs-layout/tabs-state.js +73 -61
- package/dist/ui-defaults/index.d.ts +2 -2
- package/dist/ui-defaults/list-screen.d.ts +2 -3
- package/dist/ui-defaults/list-screen.js +33 -37
- package/dist/ui-defaults/markdown-field.js +24 -56
- package/dist/ui-router/routes-loader.d.ts +1 -1
- package/dist/ui-router/routes-loader.js +17 -13
- package/dist/ui-router/ui-loader.d.ts +6 -6
- package/dist/ui-router/ui-loader.js +172 -268
- package/dist/utils.js +49 -39
- package/jest.config.js +16 -16
- package/package.json +16 -14
- package/src/command-palette/command-palette-ui.tsx +261 -237
- package/src/command-palette/command-palette.ts +81 -78
- package/src/components/chat-overlay.tsx +366 -261
- package/src/components/checkbox.tsx +15 -12
- package/src/components/group-switcher.tsx +150 -105
- package/src/components/input-date.tsx +17 -16
- package/src/components/input-number.tsx +47 -31
- package/src/components/input.tsx +15 -12
- package/src/components/inverse-lazy-list.tsx +14 -13
- package/src/components/io-schema-values.tsx +51 -69
- package/src/components/io-schema.tsx +94 -69
- package/src/components/lazy-list.tsx +51 -34
- package/src/components/list-screen.tsx +51 -35
- package/src/components/loading-indicator.tsx +2 -4
- package/src/components/markdown-editor/autolink-plugin.tsx +4 -11
- package/src/components/markdown-editor/editor-inline.tsx +3 -4
- package/src/components/markdown-editor/editor.tsx +53 -51
- package/src/components/markdown-editor/markdown-plugin.tsx +48 -40
- package/src/components/markdown-editor/mention-node.ts +39 -38
- package/src/components/markdown-editor/mentions-plugin.tsx +99 -101
- package/src/components/markdown-editor/theme.ts +28 -29
- package/src/components/markdown-editor/toolbar.tsx +53 -47
- package/src/components/markdown-with-mentions.tsx +56 -46
- package/src/components/message-logs/message-logs.tsx +225 -165
- package/src/components/messages/avatar.tsx +70 -52
- package/src/components/messages/channel-message-list.tsx +80 -68
- package/src/components/messages/channel-view.tsx +34 -33
- package/src/components/messages/message-compose.tsx +84 -67
- package/src/components/messages/message-display.tsx +103 -89
- package/src/components/messages/thread-message-list.tsx +53 -44
- package/src/components/router.tsx +42 -43
- package/src/components/save-button.tsx +43 -39
- package/src/components/sortable-list.tsx +77 -49
- package/src/components/tabs.tsx +31 -31
- package/src/components/tooltip.tsx +21 -28
- package/src/components/trust-level-badge.tsx +15 -11
- package/src/components/trust-level-dropdown.tsx +49 -19
- package/src/components/typeahead.tsx +57 -59
- package/src/components/voice-indicator.tsx +158 -141
- package/src/components/voice-subscribe-events.ts +20 -0
- package/src/globals.tsx +42 -40
- package/src/hooks.test.tsx +141 -134
- package/src/hooks.ts +80 -48
- package/src/index.tsx +17 -10
- package/src/mention-configs.ts +122 -68
- package/src/screens/assistants/assistant-config.tsx +28 -18
- package/src/screens/assistants/assistant-details.tsx +35 -36
- package/src/screens/assistants/assistant-info.tsx +16 -11
- package/src/screens/assistants/assistant-list.tsx +37 -34
- package/src/screens/assistants/assistant-tools.tsx +41 -20
- package/src/screens/console-logs/console-logs-list.tsx +173 -140
- package/src/screens/console-logs/log-display.tsx +65 -38
- package/src/screens/console-logs/log-filters.tsx +4 -3
- package/src/screens/console-logs/mobile-log-card.tsx +78 -71
- package/src/screens/console-logs/resizable-table-header.tsx +29 -21
- package/src/screens/contacts/contact-details.tsx +29 -30
- package/src/screens/contacts/contact-list.tsx +71 -60
- package/src/screens/contacts/index.ts +5 -5
- package/src/screens/contacts/user-connect.tsx +177 -171
- package/src/screens/data-explorer/data-explorer.tsx +134 -98
- package/src/screens/data-explorer/index.ts +2 -3
- package/src/screens/data-explorer/query-executor.tsx +90 -80
- package/src/screens/groups/group-details.tsx +120 -101
- package/src/screens/groups/group-invite-listener.tsx +34 -37
- package/src/screens/groups/group-list.tsx +119 -103
- package/src/screens/groups/group-members.tsx +225 -164
- package/src/screens/groups/index.ts +5 -6
- package/src/screens/join-group/index.ts +2 -2
- package/src/screens/join-group/join-group.tsx +41 -39
- package/src/screens/network-viewer/connection-troubleshooter.tsx +145 -104
- package/src/screens/network-viewer/cpu-usage-graph.tsx +39 -43
- package/src/screens/network-viewer/device-details-modal.tsx +46 -59
- package/src/screens/network-viewer/group-details-modal.tsx +68 -49
- package/src/screens/network-viewer/index.ts +4 -5
- package/src/screens/network-viewer/network-viewer-ipc.ts +23 -0
- package/src/screens/network-viewer/network-viewer.tsx +261 -236
- package/src/screens/network-viewer/usage-graph.tsx +57 -49
- package/src/screens/packages/package-details.tsx +43 -35
- package/src/screens/packages/package-info.tsx +107 -66
- package/src/screens/packages/package-list.tsx +175 -98
- package/src/screens/packages/package-new-local.tsx +28 -26
- package/src/screens/packages/package-versions.tsx +102 -77
- package/src/screens/peer-types/peer-type-details.tsx +60 -50
- package/src/screens/peer-types/peer-type-list.tsx +20 -30
- package/src/screens/search/global-search.tsx +153 -137
- package/src/screens/settings/color-mode-dropdown.tsx +52 -35
- package/src/screens/settings/settings-page.tsx +215 -141
- package/src/screens/settings/voice-settings-agent.tsx +13 -12
- package/src/screens/settings/voice-settings-api-keys.tsx +14 -12
- package/src/screens/settings/voice-settings-output.tsx +12 -11
- package/src/screens/settings/voice-settings-providers.tsx +7 -3
- package/src/screens/settings/voice-settings-types.ts +52 -49
- package/src/screens/settings/voice-settings-wake-word.tsx +25 -9
- package/src/screens/settings/voice-settings.tsx +66 -43
- package/src/screens/setup-user.tsx +88 -41
- package/src/screens/tools/tool-code.tsx +12 -17
- package/src/screens/tools/tool-details.tsx +28 -28
- package/src/screens/tools/tool-info.tsx +14 -19
- package/src/screens/tools/tool-list.tsx +58 -40
- package/src/screens/tools/tool-schema.tsx +16 -9
- package/src/screens/tools/tool-test-details.tsx +11 -22
- package/src/screens/tools/tool-test-list.tsx +29 -30
- package/src/screens/variables/variable-details.tsx +63 -51
- package/src/screens/variables/variable-list.tsx +29 -30
- package/src/screens/welcome-modal.tsx +68 -48
- package/src/screens/workflows/workflow-details.tsx +40 -30
- package/src/screens/workflows/workflow-info.tsx +4 -11
- package/src/screens/workflows/workflow-instructions.tsx +35 -28
- package/src/screens/workflows/workflow-list.tsx +50 -40
- package/src/setupTests.ts +14 -13
- package/src/system-apps/assistants.app.ts +5 -5
- package/src/system-apps/console-logs.app.ts +4 -4
- package/src/system-apps/contacts.app.ts +6 -6
- package/src/system-apps/data-explorer.app.ts +5 -5
- package/src/system-apps/groups.app.ts +6 -6
- package/src/system-apps/index.ts +49 -49
- package/src/system-apps/join-group.app.ts +5 -5
- package/src/system-apps/mobile-settings.app.ts +4 -5
- package/src/system-apps/network-viewer.app.ts +5 -5
- package/src/system-apps/packages.app.ts +5 -5
- package/src/system-apps/search.app.ts +6 -6
- package/src/system-apps/settings.app.ts +5 -5
- package/src/system-apps/threads.app.ts +5 -5
- package/src/system-apps/tools.app.ts +5 -5
- package/src/system-apps/types.app.ts +5 -5
- package/src/system-apps/variables.app.ts +5 -5
- package/src/system-apps/workflows.app.ts +5 -5
- package/src/tabs-layout/tabs-layout.tsx +345 -254
- package/src/tabs-layout/tabs-state.ts +100 -81
- package/src/ui-defaults/index.ts +2 -3
- package/src/ui-defaults/list-screen.tsx +45 -40
- package/src/ui-defaults/markdown-field.tsx +22 -26
- package/src/ui-router/routes-loader.ts +40 -24
- package/src/ui-router/ui-loader.tsx +312 -214
- package/src/utils.ts +68 -81
- package/tsconfig.json +5 -10
- package/dist/components/input-datetime.d.ts +0 -7
- package/dist/components/input-datetime.js +0 -35
- package/dist/components/lazy-sortable-list.d.ts +0 -29
- package/dist/components/lazy-sortable-list.js +0 -12
- package/dist/components/left-bar.d.ts +0 -5
- package/dist/components/left-bar.js +0 -207
- package/dist/components/main-content-container.d.ts +0 -2
- package/dist/components/main-content-container.js +0 -92
- package/dist/components/messages/thread-view.d.ts +0 -6
- package/dist/components/messages/thread-view.js +0 -174
- package/dist/components/off-canvas.d.ts +0 -13
- package/dist/components/off-canvas.js +0 -89
- package/dist/components/text-list-editor.tsx/text-list-editor.d.ts +0 -6
- package/dist/components/text-list-editor.tsx/text-list-editor.js +0 -13
- package/dist/components/top-bar.d.ts +0 -2
- package/dist/components/top-bar.js +0 -51
- package/dist/components/typeahead/mentions-plugin.d.ts +0 -7
- package/dist/components/typeahead/mentions-plugin.js +0 -203
- package/dist/components/typeahead/typeahead-editor.d.ts +0 -15
- package/dist/components/typeahead/typeahead-editor.js +0 -134
- package/dist/components/typeahead/typeahead.d.ts +0 -12
- package/dist/components/typeahead/typeahead.js +0 -94
- package/dist/screens/profile.d.ts +0 -2
- package/dist/screens/profile.js +0 -76
- package/src/components/input-datetime.tsx +0 -41
- package/src/components/lazy-sortable-list.tsx +0 -51
- package/src/components/left-bar.tsx +0 -322
- package/src/components/main-content-container.tsx +0 -79
- package/src/components/messages/thread-view.tsx +0 -214
- package/src/components/off-canvas.tsx +0 -83
- package/src/components/text-list-editor.tsx/text-list-editor.tsx +0 -13
- package/src/components/top-bar.tsx +0 -119
- package/src/components/typeahead/mentions-plugin.tsx +0 -265
- package/src/components/typeahead/typeahead-editor.tsx +0 -140
- package/src/components/typeahead/typeahead.tsx +0 -77
- package/src/screens/profile.tsx +0 -75
|
@@ -1,18 +1,32 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
import {
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
12
|
-
import {
|
|
13
|
-
import {
|
|
14
|
-
import {
|
|
15
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
getUserContext,
|
|
3
|
+
hasShownWelcomeModal,
|
|
4
|
+
type IAppNav,
|
|
5
|
+
rpcServerCalls,
|
|
6
|
+
type Subscription,
|
|
7
|
+
setDefaultClientUserContext,
|
|
8
|
+
} from "@peers-app/peers-sdk";
|
|
9
|
+
import React, { Component, useEffect, useState } from "react";
|
|
10
|
+
import { openCommandPalette } from "../command-palette/command-palette";
|
|
11
|
+
import { CommandPaletteOverlay } from "../command-palette/command-palette-ui";
|
|
12
|
+
import { GroupSwitcher } from "../components/group-switcher";
|
|
13
|
+
import { Router } from "../components/router";
|
|
14
|
+
import { isDesktop, loadGlobals } from "../globals";
|
|
15
|
+
import { useObservable, usePromise } from "../hooks";
|
|
16
|
+
import { colorMode } from "../screens/settings/color-mode-dropdown";
|
|
17
|
+
import { SetupUser } from "../screens/setup-user";
|
|
18
|
+
import { WelcomeModal } from "../screens/welcome-modal";
|
|
19
|
+
import { systemPackage } from "../system-apps";
|
|
20
|
+
import { allPackages, loadAllRoutes } from "../ui-router/routes-loader";
|
|
21
|
+
import { UIRouter } from "../ui-router/ui-loader";
|
|
22
|
+
import {
|
|
23
|
+
activeTabId,
|
|
24
|
+
activeTabs,
|
|
25
|
+
goToTabPath,
|
|
26
|
+
initializedTabs,
|
|
27
|
+
recentlyUsedApps,
|
|
28
|
+
type TabState,
|
|
29
|
+
} from "./tabs-state";
|
|
16
30
|
|
|
17
31
|
// Error boundary that wraps each tab's content so a crash in one tab
|
|
18
32
|
// doesn't take down the entire app.
|
|
@@ -38,18 +52,30 @@ class TabErrorBoundary extends Component<TabErrorBoundaryProps, TabErrorBoundary
|
|
|
38
52
|
}
|
|
39
53
|
|
|
40
54
|
componentDidCatch(error: Error, errorInfo: React.ErrorInfo) {
|
|
41
|
-
console.error(
|
|
55
|
+
console.error(
|
|
56
|
+
`TabErrorBoundary caught error in tab "${this.props.tabTitle}":`,
|
|
57
|
+
error,
|
|
58
|
+
errorInfo,
|
|
59
|
+
);
|
|
42
60
|
}
|
|
43
61
|
|
|
44
62
|
render() {
|
|
45
63
|
if (this.state.hasError) {
|
|
46
64
|
return (
|
|
47
|
-
<div style={{ padding:
|
|
48
|
-
<h4 style={{ marginBottom:
|
|
49
|
-
<p
|
|
50
|
-
{
|
|
65
|
+
<div style={{ padding: "24px", textAlign: "center" }}>
|
|
66
|
+
<h4 style={{ marginBottom: "12px" }}>Something went wrong in "{this.props.tabTitle}"</h4>
|
|
67
|
+
<p
|
|
68
|
+
style={{
|
|
69
|
+
opacity: 0.7,
|
|
70
|
+
marginBottom: "16px",
|
|
71
|
+
fontFamily: "monospace",
|
|
72
|
+
fontSize: "13px",
|
|
73
|
+
}}
|
|
74
|
+
>
|
|
75
|
+
{this.state.error?.message || "Unknown error"}
|
|
51
76
|
</p>
|
|
52
77
|
<button
|
|
78
|
+
type="button"
|
|
53
79
|
className="btn btn-outline-primary btn-sm"
|
|
54
80
|
onClick={() => this.setState({ hasError: false, error: null })}
|
|
55
81
|
>
|
|
@@ -65,7 +91,7 @@ class TabErrorBoundary extends Component<TabErrorBoundaryProps, TabErrorBoundary
|
|
|
65
91
|
export function TabsLayoutApp() {
|
|
66
92
|
const userId = usePromise(async () => {
|
|
67
93
|
const _userId = await rpcServerCalls.getUserId();
|
|
68
|
-
return _userId || null as string | null;
|
|
94
|
+
return _userId || (null as string | null);
|
|
69
95
|
});
|
|
70
96
|
|
|
71
97
|
if (userId === undefined) {
|
|
@@ -73,7 +99,7 @@ export function TabsLayoutApp() {
|
|
|
73
99
|
}
|
|
74
100
|
|
|
75
101
|
if (!userId) {
|
|
76
|
-
document.getElementById(
|
|
102
|
+
document.getElementById("appLoadingDiv")?.remove();
|
|
77
103
|
return <SetupUser />;
|
|
78
104
|
} else {
|
|
79
105
|
return <TabsLayout userId={userId} />;
|
|
@@ -86,7 +112,7 @@ export function TabsLayout(props: { userId: string }) {
|
|
|
86
112
|
setDefaultClientUserContext(props.userId);
|
|
87
113
|
userContextInitialized = true;
|
|
88
114
|
}
|
|
89
|
-
|
|
115
|
+
|
|
90
116
|
const loaded = usePromise(async () => {
|
|
91
117
|
await loadGlobals();
|
|
92
118
|
await loadAllRoutes();
|
|
@@ -111,17 +137,14 @@ export function TabsLayout(props: { userId: string }) {
|
|
|
111
137
|
|
|
112
138
|
if (!loaded) return false;
|
|
113
139
|
|
|
114
|
-
document.getElementById(
|
|
140
|
+
document.getElementById("appLoadingDiv")?.remove();
|
|
115
141
|
|
|
116
142
|
return (
|
|
117
143
|
<>
|
|
118
144
|
<TabsLayoutInternal />
|
|
119
145
|
<CommandPaletteOverlay />
|
|
120
146
|
{showWelcomeModal && (
|
|
121
|
-
<WelcomeModal
|
|
122
|
-
colorMode={_colorMode}
|
|
123
|
-
onClose={() => setShowWelcomeModal(false)}
|
|
124
|
-
/>
|
|
147
|
+
<WelcomeModal colorMode={_colorMode} onClose={() => setShowWelcomeModal(false)} />
|
|
125
148
|
)}
|
|
126
149
|
</>
|
|
127
150
|
);
|
|
@@ -131,14 +154,14 @@ function TabsLayoutInternal() {
|
|
|
131
154
|
const [_colorMode] = useObservable(colorMode);
|
|
132
155
|
const [tabs] = useObservable(activeTabs);
|
|
133
156
|
const [activeTab] = useObservable(activeTabId);
|
|
134
|
-
const [currentlyActiveGroupId, setCurrentlyActiveGroupId] = useState(
|
|
157
|
+
const [currentlyActiveGroupId, setCurrentlyActiveGroupId] = useState("");
|
|
135
158
|
const [switchingGroup, setSwitchingGroup] = useState(false);
|
|
136
|
-
|
|
159
|
+
|
|
137
160
|
useEffect(() => {
|
|
138
161
|
let sub: Subscription;
|
|
139
|
-
getUserContext().then(userContext => {
|
|
140
|
-
setCurrentlyActiveGroupId(userContext.currentlyActiveGroupId() || userContext.userId)
|
|
141
|
-
sub = userContext.currentlyActiveGroupId.subscribe(async
|
|
162
|
+
getUserContext().then((userContext) => {
|
|
163
|
+
setCurrentlyActiveGroupId(userContext.currentlyActiveGroupId() || userContext.userId);
|
|
164
|
+
sub = userContext.currentlyActiveGroupId.subscribe(async (_groupId) => {
|
|
142
165
|
setCurrentlyActiveGroupId(userContext.currentlyActiveGroupId() || userContext.userId);
|
|
143
166
|
setSwitchingGroup(true);
|
|
144
167
|
await userContext.waitForActiveGroupPersistence();
|
|
@@ -152,24 +175,24 @@ function TabsLayoutInternal() {
|
|
|
152
175
|
}
|
|
153
176
|
};
|
|
154
177
|
}, []);
|
|
155
|
-
|
|
178
|
+
|
|
156
179
|
useObservable(isDesktop);
|
|
157
180
|
const isMobile = !isDesktop();
|
|
158
181
|
|
|
159
182
|
const closeTab = (tabId: string) => {
|
|
160
183
|
const currentTabs = activeTabs();
|
|
161
|
-
const tabToClose = currentTabs.find(t => t.tabId === tabId);
|
|
184
|
+
const tabToClose = currentTabs.find((t) => t.tabId === tabId);
|
|
162
185
|
|
|
163
186
|
if (!tabToClose || tabToClose.tabId === "launcher") return;
|
|
164
187
|
|
|
165
|
-
const closedIndex = currentTabs.findIndex(t => t.tabId === tabId);
|
|
166
|
-
const newTabs = currentTabs.filter(t => t.tabId !== tabId);
|
|
188
|
+
const closedIndex = currentTabs.findIndex((t) => t.tabId === tabId);
|
|
189
|
+
const newTabs = currentTabs.filter((t) => t.tabId !== tabId);
|
|
167
190
|
activeTabs(newTabs);
|
|
168
191
|
initializedTabs.delete(tabId);
|
|
169
192
|
|
|
170
193
|
if (activeTab === tabId) {
|
|
171
194
|
if (newTabs.length === 0) {
|
|
172
|
-
activeTabId(
|
|
195
|
+
activeTabId("launcher");
|
|
173
196
|
} else if (closedIndex < newTabs.length) {
|
|
174
197
|
activeTabId(newTabs[closedIndex].tabId);
|
|
175
198
|
} else {
|
|
@@ -185,25 +208,35 @@ function TabsLayoutInternal() {
|
|
|
185
208
|
return (
|
|
186
209
|
<div
|
|
187
210
|
key={currentlyActiveGroupId}
|
|
188
|
-
className="d-flex flex-column"
|
|
211
|
+
className="d-flex flex-column"
|
|
212
|
+
style={{ height: "calc(100vh - 25px)", overflow: "hidden" }}
|
|
213
|
+
>
|
|
189
214
|
{switchingGroup && (
|
|
190
|
-
<div
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
215
|
+
<div
|
|
216
|
+
style={{
|
|
217
|
+
position: "fixed",
|
|
218
|
+
inset: 0,
|
|
219
|
+
zIndex: 9999,
|
|
220
|
+
display: "flex",
|
|
221
|
+
alignItems: "center",
|
|
222
|
+
justifyContent: "center",
|
|
223
|
+
backgroundColor: _colorMode === "light" ? "rgba(255,255,255,0.85)" : "rgba(0,0,0,0.85)",
|
|
224
|
+
}}
|
|
225
|
+
>
|
|
195
226
|
<div className="text-center">
|
|
196
227
|
<div className="spinner-border text-secondary mb-3" role="status" />
|
|
197
|
-
<div className={`small ${_colorMode ===
|
|
228
|
+
<div className={`small ${_colorMode === "light" ? "text-muted" : "text-secondary"}`}>
|
|
229
|
+
Switching group...
|
|
230
|
+
</div>
|
|
198
231
|
</div>
|
|
199
232
|
</div>
|
|
200
233
|
)}
|
|
201
234
|
{/* Tabs Header */}
|
|
202
235
|
<div
|
|
203
|
-
className={`border-bottom ${_colorMode ===
|
|
236
|
+
className={`border-bottom ${_colorMode === "light" ? "bg-light" : "bg-dark"}`}
|
|
204
237
|
style={{
|
|
205
|
-
borderBottomWidth:
|
|
206
|
-
borderBottomColor: _colorMode ===
|
|
238
|
+
borderBottomWidth: "1px",
|
|
239
|
+
borderBottomColor: _colorMode === "light" ? "#dee2e6" : "#495057",
|
|
207
240
|
}}
|
|
208
241
|
>
|
|
209
242
|
{isMobile ? (
|
|
@@ -215,43 +248,45 @@ function TabsLayoutInternal() {
|
|
|
215
248
|
colorMode={_colorMode}
|
|
216
249
|
/>
|
|
217
250
|
) : (
|
|
218
|
-
<div className="d-flex align-items-center px-1" style={{ height:
|
|
251
|
+
<div className="d-flex align-items-center px-1" style={{ height: "36px" }}>
|
|
219
252
|
{/* Group Switcher */}
|
|
220
253
|
<GroupSwitcher colorMode={_colorMode} isMobile={false} />
|
|
221
|
-
|
|
254
|
+
|
|
222
255
|
{/* Search Button */}
|
|
223
256
|
<button
|
|
257
|
+
type="button"
|
|
224
258
|
className="btn btn-sm me-2 d-flex align-items-center"
|
|
225
259
|
onClick={openCommandPalette}
|
|
226
260
|
title="Search everything (Cmd+K)"
|
|
227
261
|
style={{
|
|
228
|
-
padding:
|
|
229
|
-
fontSize:
|
|
230
|
-
borderRadius:
|
|
231
|
-
border:
|
|
232
|
-
background:
|
|
233
|
-
color: _colorMode ===
|
|
262
|
+
padding: "4px 8px",
|
|
263
|
+
fontSize: "12px",
|
|
264
|
+
borderRadius: "6px",
|
|
265
|
+
border: "none",
|
|
266
|
+
background: "transparent",
|
|
267
|
+
color: _colorMode === "light" ? "#6c757d" : "#adb5bd",
|
|
234
268
|
}}
|
|
235
269
|
onMouseEnter={(e) => {
|
|
236
|
-
e.currentTarget.style.backgroundColor =
|
|
237
|
-
|
|
270
|
+
e.currentTarget.style.backgroundColor =
|
|
271
|
+
_colorMode === "light" ? "#f8f9fa" : "#495057";
|
|
272
|
+
e.currentTarget.style.color = _colorMode === "light" ? "#0d6efd" : "#ffffff";
|
|
238
273
|
}}
|
|
239
274
|
onMouseLeave={(e) => {
|
|
240
|
-
e.currentTarget.style.backgroundColor =
|
|
241
|
-
e.currentTarget.style.color = _colorMode ===
|
|
275
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
276
|
+
e.currentTarget.style.color = _colorMode === "light" ? "#6c757d" : "#adb5bd";
|
|
242
277
|
}}
|
|
243
278
|
>
|
|
244
|
-
<i className="bi-search" style={{ fontSize:
|
|
279
|
+
<i className="bi-search" style={{ fontSize: "14px" }} />
|
|
245
280
|
</button>
|
|
246
|
-
|
|
281
|
+
|
|
247
282
|
<div
|
|
248
283
|
className="d-flex flex-grow-1 overflow-auto"
|
|
249
284
|
style={{
|
|
250
|
-
scrollbarWidth:
|
|
251
|
-
msOverflowStyle:
|
|
285
|
+
scrollbarWidth: "none",
|
|
286
|
+
msOverflowStyle: "none",
|
|
252
287
|
}}
|
|
253
288
|
>
|
|
254
|
-
{tabs.map(tab => (
|
|
289
|
+
{tabs.map((tab) => (
|
|
255
290
|
<TabHeader
|
|
256
291
|
key={tab.tabId}
|
|
257
292
|
tab={tab}
|
|
@@ -268,11 +303,11 @@ function TabsLayoutInternal() {
|
|
|
268
303
|
|
|
269
304
|
{/* Tab Content */}
|
|
270
305
|
<div className="flex-grow-1 overflow-hidden">
|
|
271
|
-
{tabs.map(tab => (
|
|
306
|
+
{tabs.map((tab) => (
|
|
272
307
|
<div
|
|
273
308
|
key={tab.tabId}
|
|
274
|
-
className={`h-100 ${activeTab === tab.tabId ?
|
|
275
|
-
style={{ display: activeTab === tab.tabId ?
|
|
309
|
+
className={`h-100 ${activeTab === tab.tabId ? "d-block" : "d-none"}`}
|
|
310
|
+
style={{ display: activeTab === tab.tabId ? "block" : "none" }}
|
|
276
311
|
>
|
|
277
312
|
<TabErrorBoundary tabTitle={tab.title} tabId={tab.tabId}>
|
|
278
313
|
<TabContent tab={tab} isMobile={isMobile} isActive={activeTab === tab.tabId} />
|
|
@@ -292,112 +327,131 @@ interface MobileTabsHeaderProps {
|
|
|
292
327
|
colorMode: string;
|
|
293
328
|
}
|
|
294
329
|
|
|
295
|
-
function MobileTabsHeader({
|
|
330
|
+
function MobileTabsHeader({
|
|
331
|
+
tabs,
|
|
332
|
+
activeTab,
|
|
333
|
+
onSwitch,
|
|
334
|
+
onClose,
|
|
335
|
+
colorMode,
|
|
336
|
+
}: MobileTabsHeaderProps) {
|
|
296
337
|
const [showMenuDropdown, setShowMenuDropdown] = React.useState(false);
|
|
297
|
-
const currentTab = tabs.find(t => t.tabId === activeTab);
|
|
298
|
-
const nonLauncherTabs = tabs.filter(t => t.packageId !==
|
|
338
|
+
const currentTab = tabs.find((t) => t.tabId === activeTab);
|
|
339
|
+
const nonLauncherTabs = tabs.filter((t) => t.packageId !== "launcher");
|
|
299
340
|
|
|
300
341
|
return (
|
|
301
|
-
<div
|
|
342
|
+
<div
|
|
343
|
+
className="d-flex align-items-center justify-content-between px-2 position-relative"
|
|
344
|
+
style={{ height: "36px" }}
|
|
345
|
+
>
|
|
302
346
|
{/* Left Side - Group Switcher */}
|
|
303
347
|
<div className="d-flex align-items-center gap-1">
|
|
304
348
|
<GroupSwitcher colorMode={colorMode} isMobile={true} />
|
|
305
349
|
</div>
|
|
306
350
|
|
|
307
351
|
{/* Center - Current Tab Display (absolutely positioned to center on screen) */}
|
|
308
|
-
<div
|
|
352
|
+
<div
|
|
309
353
|
className="d-flex align-items-center justify-content-center position-absolute"
|
|
310
|
-
style={{
|
|
311
|
-
left:
|
|
312
|
-
transform:
|
|
313
|
-
pointerEvents:
|
|
314
|
-
maxWidth:
|
|
354
|
+
style={{
|
|
355
|
+
left: "50%",
|
|
356
|
+
transform: "translateX(-50%)",
|
|
357
|
+
pointerEvents: "none",
|
|
358
|
+
maxWidth: "calc(100% - 140px)",
|
|
315
359
|
}}
|
|
316
360
|
>
|
|
317
|
-
{currentTab?.iconClassName && currentTab.packageId !==
|
|
361
|
+
{currentTab?.iconClassName && currentTab.packageId !== "launcher" && (
|
|
318
362
|
<i className={`${currentTab.iconClassName} me-2`} />
|
|
319
363
|
)}
|
|
320
|
-
<span className="fw-medium text-truncate small">
|
|
321
|
-
{currentTab?.title || 'Apps'}
|
|
322
|
-
</span>
|
|
364
|
+
<span className="fw-medium text-truncate small">{currentTab?.title || "Apps"}</span>
|
|
323
365
|
</div>
|
|
324
366
|
|
|
325
367
|
{/* Right Side - Hamburger Menu */}
|
|
326
368
|
<div className="d-flex align-items-center">
|
|
327
369
|
<div className="dropdown">
|
|
328
370
|
<button
|
|
329
|
-
|
|
371
|
+
type="button"
|
|
372
|
+
className={`btn btn-sm ${colorMode === "light" ? "btn-outline-dark" : "btn-outline-light"}`}
|
|
330
373
|
onClick={() => setShowMenuDropdown(!showMenuDropdown)}
|
|
331
|
-
style={{ minWidth:
|
|
374
|
+
style={{ minWidth: "36px" }}
|
|
332
375
|
>
|
|
333
376
|
<i className="bi-list" />
|
|
334
|
-
{nonLauncherTabs.length > 0 &&
|
|
335
|
-
<span className="ms-1">{nonLauncherTabs.length}</span>
|
|
336
|
-
)}
|
|
377
|
+
{nonLauncherTabs.length > 0 && <span className="ms-1">{nonLauncherTabs.length}</span>}
|
|
337
378
|
</button>
|
|
338
379
|
{showMenuDropdown && (
|
|
339
380
|
<div
|
|
340
|
-
className={`dropdown-menu show position-absolute ${colorMode ===
|
|
341
|
-
style={{
|
|
381
|
+
className={`dropdown-menu show position-absolute ${colorMode === "light" ? "" : "dropdown-menu-dark"}`}
|
|
382
|
+
style={{
|
|
383
|
+
right: 0,
|
|
384
|
+
top: "100%",
|
|
385
|
+
zIndex: 1000,
|
|
386
|
+
minWidth: "280px",
|
|
387
|
+
maxHeight: "calc(100vh - 60px)",
|
|
388
|
+
overflowY: "auto",
|
|
389
|
+
}}
|
|
342
390
|
>
|
|
343
391
|
{/* Apps Option */}
|
|
344
392
|
<div
|
|
345
|
-
className={`dropdown-item d-flex align-items-center ${activeTab ===
|
|
346
|
-
style={{ cursor:
|
|
393
|
+
className={`dropdown-item d-flex align-items-center ${activeTab === "launcher" ? "active" : ""}`}
|
|
394
|
+
style={{ cursor: "pointer", padding: "14px 18px", fontSize: "17px" }}
|
|
347
395
|
onClick={() => {
|
|
348
|
-
onSwitch(
|
|
396
|
+
onSwitch("launcher");
|
|
349
397
|
setShowMenuDropdown(false);
|
|
350
398
|
}}
|
|
351
399
|
>
|
|
352
|
-
<i className="bi-grid-3x3-gap me-3" style={{ fontSize:
|
|
400
|
+
<i className="bi-grid-3x3-gap me-3" style={{ fontSize: "20px" }} />
|
|
353
401
|
<span>Apps</span>
|
|
354
402
|
</div>
|
|
355
|
-
|
|
403
|
+
|
|
356
404
|
{/* Search Option */}
|
|
357
405
|
<div
|
|
358
406
|
className="dropdown-item d-flex align-items-center"
|
|
359
|
-
style={{ cursor:
|
|
407
|
+
style={{ cursor: "pointer", padding: "14px 18px", fontSize: "17px" }}
|
|
360
408
|
onClick={() => {
|
|
361
409
|
openCommandPalette();
|
|
362
410
|
setShowMenuDropdown(false);
|
|
363
411
|
}}
|
|
364
412
|
>
|
|
365
|
-
<i className="bi-search me-3" style={{ fontSize:
|
|
413
|
+
<i className="bi-search me-3" style={{ fontSize: "20px" }} />
|
|
366
414
|
<span>Search</span>
|
|
367
415
|
</div>
|
|
368
|
-
|
|
416
|
+
|
|
369
417
|
{/* Divider if there are open tabs */}
|
|
370
418
|
{nonLauncherTabs.length > 0 && (
|
|
371
|
-
<div className="dropdown-divider" style={{ margin:
|
|
419
|
+
<div className="dropdown-divider" style={{ margin: "8px 0" }} />
|
|
372
420
|
)}
|
|
373
|
-
|
|
421
|
+
|
|
374
422
|
{/* Open Tabs */}
|
|
375
|
-
{nonLauncherTabs
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
{tab.iconClassName && <i className={`${tab.iconClassName} me-3`} style={{ fontSize: '20px' }} />}
|
|
387
|
-
<span>{tab.title}</span>
|
|
388
|
-
</div>
|
|
389
|
-
<button
|
|
390
|
-
className="btn btn-sm p-0 ms-3"
|
|
391
|
-
style={{ width: '32px', height: '32px', fontSize: '20px' }}
|
|
392
|
-
onClick={(e) => {
|
|
393
|
-
e.stopPropagation();
|
|
394
|
-
onClose(tab.tabId);
|
|
423
|
+
{nonLauncherTabs
|
|
424
|
+
.slice()
|
|
425
|
+
.reverse()
|
|
426
|
+
.map((tab) => (
|
|
427
|
+
<div
|
|
428
|
+
key={tab.tabId}
|
|
429
|
+
className={`dropdown-item d-flex align-items-center justify-content-between ${activeTab === tab.tabId ? "active" : ""}`}
|
|
430
|
+
style={{ cursor: "pointer", padding: "14px 18px", fontSize: "17px" }}
|
|
431
|
+
onClick={() => {
|
|
432
|
+
onSwitch(tab.tabId);
|
|
433
|
+
setShowMenuDropdown(false);
|
|
395
434
|
}}
|
|
396
435
|
>
|
|
397
|
-
<
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
436
|
+
<div className="d-flex align-items-center">
|
|
437
|
+
{tab.iconClassName && (
|
|
438
|
+
<i className={`${tab.iconClassName} me-3`} style={{ fontSize: "20px" }} />
|
|
439
|
+
)}
|
|
440
|
+
<span>{tab.title}</span>
|
|
441
|
+
</div>
|
|
442
|
+
<button
|
|
443
|
+
type="button"
|
|
444
|
+
className="btn btn-sm p-0 ms-3"
|
|
445
|
+
style={{ width: "32px", height: "32px", fontSize: "20px" }}
|
|
446
|
+
onClick={(e) => {
|
|
447
|
+
e.stopPropagation();
|
|
448
|
+
onClose(tab.tabId);
|
|
449
|
+
}}
|
|
450
|
+
>
|
|
451
|
+
<i className="bi-x" />
|
|
452
|
+
</button>
|
|
453
|
+
</div>
|
|
454
|
+
))}
|
|
401
455
|
</div>
|
|
402
456
|
)}
|
|
403
457
|
</div>
|
|
@@ -425,59 +479,70 @@ interface TabHeaderProps {
|
|
|
425
479
|
|
|
426
480
|
function TabHeader({ tab, isActive, onSwitch, onClose, colorMode }: TabHeaderProps) {
|
|
427
481
|
const activeClass = isActive
|
|
428
|
-
?
|
|
429
|
-
|
|
482
|
+
? colorMode === "light"
|
|
483
|
+
? "bg-white"
|
|
484
|
+
: "bg-secondary"
|
|
485
|
+
: colorMode === "light"
|
|
486
|
+
? "bg-light"
|
|
487
|
+
: "bg-dark";
|
|
430
488
|
|
|
431
489
|
return (
|
|
432
490
|
<div
|
|
433
491
|
className={`d-flex align-items-center px-2 py-1 user-select-none ${activeClass}`}
|
|
434
492
|
style={{
|
|
435
|
-
cursor:
|
|
436
|
-
minWidth:
|
|
437
|
-
maxWidth:
|
|
438
|
-
height:
|
|
439
|
-
fontSize:
|
|
440
|
-
borderTop: isActive ?
|
|
441
|
-
borderLeft:
|
|
442
|
-
borderRight:
|
|
443
|
-
borderBottom: isActive
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
493
|
+
cursor: "pointer",
|
|
494
|
+
minWidth: "100px",
|
|
495
|
+
maxWidth: "180px",
|
|
496
|
+
height: "34px",
|
|
497
|
+
fontSize: "13px",
|
|
498
|
+
borderTop: isActive ? "2px solid #0d6efd" : "2px solid transparent",
|
|
499
|
+
borderLeft: "1px solid transparent",
|
|
500
|
+
borderRight: `1px solid ${colorMode === "light" ? "#dee2e6" : "#495057"}`,
|
|
501
|
+
borderBottom: isActive
|
|
502
|
+
? colorMode === "light"
|
|
503
|
+
? "1px solid white"
|
|
504
|
+
: "1px solid #343a40"
|
|
505
|
+
: "none",
|
|
506
|
+
marginBottom: isActive ? "-1px" : "0",
|
|
507
|
+
borderRadius: isActive ? "6px 6px 0 0" : "0",
|
|
508
|
+
transition: "all 0.15s ease",
|
|
447
509
|
zIndex: isActive ? 1 : 0,
|
|
448
|
-
boxShadow: isActive ?
|
|
510
|
+
boxShadow: isActive ? "0 2px 4px rgba(0,0,0,0.1)" : "none",
|
|
449
511
|
}}
|
|
450
512
|
onMouseEnter={(e) => {
|
|
451
513
|
if (!isActive) {
|
|
452
|
-
e.currentTarget.style.backgroundColor = colorMode ===
|
|
514
|
+
e.currentTarget.style.backgroundColor = colorMode === "light" ? "#f8f9fa" : "#495057";
|
|
453
515
|
}
|
|
454
516
|
}}
|
|
455
517
|
onMouseLeave={(e) => {
|
|
456
518
|
if (!isActive) {
|
|
457
|
-
e.currentTarget.style.backgroundColor = colorMode ===
|
|
519
|
+
e.currentTarget.style.backgroundColor = colorMode === "light" ? "#f1f3f4" : "#343a40";
|
|
458
520
|
}
|
|
459
521
|
}}
|
|
460
522
|
onClick={() => onSwitch(tab.tabId)}
|
|
461
523
|
>
|
|
462
|
-
{tab.iconClassName &&
|
|
463
|
-
|
|
464
|
-
)}
|
|
465
|
-
<span className="text-truncate" style={{ maxWidth: '120px', fontSize: '12px' }}>
|
|
524
|
+
{tab.iconClassName && <i className={`${tab.iconClassName} me-2`} />}
|
|
525
|
+
<span className="text-truncate" style={{ maxWidth: "120px", fontSize: "12px" }}>
|
|
466
526
|
{tab.title}
|
|
467
527
|
</span>
|
|
468
528
|
{tab.tabId !== "launcher" && (
|
|
469
529
|
<button
|
|
530
|
+
type="button"
|
|
470
531
|
className="btn p-0 ms-1 opacity-75 hover-opacity-100"
|
|
471
532
|
style={{
|
|
472
|
-
width:
|
|
473
|
-
height:
|
|
474
|
-
fontSize:
|
|
475
|
-
border:
|
|
476
|
-
background:
|
|
477
|
-
borderRadius:
|
|
533
|
+
width: "14px",
|
|
534
|
+
height: "14px",
|
|
535
|
+
fontSize: "11px",
|
|
536
|
+
border: "none",
|
|
537
|
+
background: "none",
|
|
538
|
+
borderRadius: "2px",
|
|
539
|
+
}}
|
|
540
|
+
onMouseEnter={(e) => {
|
|
541
|
+
e.currentTarget.style.backgroundColor = "rgba(0,0,0,0.1)";
|
|
542
|
+
}}
|
|
543
|
+
onMouseLeave={(e) => {
|
|
544
|
+
e.currentTarget.style.backgroundColor = "transparent";
|
|
478
545
|
}}
|
|
479
|
-
onMouseEnter={(e) => e.currentTarget.style.backgroundColor = 'rgba(0,0,0,0.1)'}
|
|
480
|
-
onMouseLeave={(e) => e.currentTarget.style.backgroundColor = 'transparent'}
|
|
481
546
|
onClick={(e) => {
|
|
482
547
|
e.stopPropagation();
|
|
483
548
|
onClose(tab.tabId);
|
|
@@ -499,7 +564,7 @@ interface TabContentProps {
|
|
|
499
564
|
function TabContent({ tab, isMobile, isActive }: TabContentProps) {
|
|
500
565
|
// Only render content if this tab is active OR has been previously initialized
|
|
501
566
|
const shouldRender = isActive || initializedTabs.has(tab.tabId);
|
|
502
|
-
|
|
567
|
+
|
|
503
568
|
// Mark tab as initialized when it becomes active for the first time
|
|
504
569
|
React.useEffect(() => {
|
|
505
570
|
if (isActive) {
|
|
@@ -515,30 +580,35 @@ function TabContent({ tab, isMobile, isActive }: TabContentProps) {
|
|
|
515
580
|
}
|
|
516
581
|
|
|
517
582
|
// Create individual tab content components that don't re-render
|
|
518
|
-
const TabContentRenderer = React.memo(
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
583
|
+
const TabContentRenderer = React.memo(
|
|
584
|
+
({ tab, isMobile }: { tab: TabState; isMobile: boolean }) => {
|
|
585
|
+
if (tab.packageId === "launcher") {
|
|
586
|
+
return <AppLauncherTab isMobile={isMobile} />;
|
|
587
|
+
}
|
|
522
588
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
589
|
+
// System apps use the main Router (which reads from mainContentPath)
|
|
590
|
+
// Package apps use UIRouter with explicit path
|
|
591
|
+
const isSystemApp = tab.packageId === "system-apps";
|
|
526
592
|
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
},
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
593
|
+
return (
|
|
594
|
+
<div className={`h-100 overflow-auto ${isMobile ? "p-2" : "p-3"}`}>
|
|
595
|
+
{isSystemApp ? (
|
|
596
|
+
<Router path={tab.path} />
|
|
597
|
+
) : (
|
|
598
|
+
<UIRouter path={tab.path} uiCategory="screen" props={{}} />
|
|
599
|
+
)}
|
|
600
|
+
</div>
|
|
601
|
+
);
|
|
602
|
+
},
|
|
603
|
+
(prevProps, nextProps) => {
|
|
604
|
+
// Only re-render if the tab or isMobile changed
|
|
605
|
+
return (
|
|
606
|
+
prevProps.tab.tabId === nextProps.tab.tabId &&
|
|
607
|
+
prevProps.tab.path === nextProps.tab.path &&
|
|
608
|
+
prevProps.isMobile === nextProps.isMobile
|
|
609
|
+
);
|
|
610
|
+
},
|
|
611
|
+
);
|
|
542
612
|
|
|
543
613
|
interface AppLauncherTabProps {
|
|
544
614
|
isMobile: boolean;
|
|
@@ -558,26 +628,28 @@ interface AppItem {
|
|
|
558
628
|
function AppLauncherTab({ isMobile }: AppLauncherTabProps) {
|
|
559
629
|
const [packages] = useObservable(allPackages);
|
|
560
630
|
const [recentApps] = useObservable(recentlyUsedApps);
|
|
561
|
-
const [searchTerm, setSearchTerm] = React.useState(
|
|
631
|
+
const [searchTerm, setSearchTerm] = React.useState("");
|
|
562
632
|
|
|
563
633
|
// Combine regular packages with system apps package
|
|
564
634
|
const allPackages_ = [...packages, systemPackage];
|
|
565
635
|
|
|
566
636
|
// Create app items from nav items in packages
|
|
567
637
|
const allApps: AppItem[] = allPackages_
|
|
568
|
-
.filter(p => !p.disabled && p.appNavs && p.appNavs.length > 0)
|
|
569
|
-
.flatMap(pkg =>
|
|
570
|
-
pkg.appNavs
|
|
638
|
+
.filter((p) => !p.disabled && p.appNavs && p.appNavs.length > 0)
|
|
639
|
+
.flatMap((pkg) => {
|
|
640
|
+
const navs = pkg.appNavs;
|
|
641
|
+
if (!navs) return [];
|
|
642
|
+
return navs.map((navItem) => {
|
|
571
643
|
// Construct path - use direct path for system apps, package-nav for others
|
|
572
644
|
let path: string;
|
|
573
|
-
if (pkg.packageId ===
|
|
645
|
+
if (pkg.packageId === "system-apps") {
|
|
574
646
|
// System apps use direct routing (like the original left bar)
|
|
575
|
-
path = navItem.navigationPath ?? navItem.name.replace(/\s/g,
|
|
647
|
+
path = navItem.navigationPath ?? navItem.name.replace(/\s/g, "-").toLowerCase();
|
|
576
648
|
} else {
|
|
577
649
|
// Regular packages use package-nav format
|
|
578
|
-
path = `package-nav/${pkg.packageId}/${(navItem.navigationPath ?? navItem.name).replace(/[^a-zA-Z0-9]/g,
|
|
579
|
-
while (path.includes(
|
|
580
|
-
path = path.replace(
|
|
650
|
+
path = `package-nav/${pkg.packageId}/${(navItem.navigationPath ?? navItem.name).replace(/[^a-zA-Z0-9]/g, "-").toLowerCase()}`;
|
|
651
|
+
while (path.includes("//")) {
|
|
652
|
+
path = path.replace("//", "/");
|
|
581
653
|
}
|
|
582
654
|
}
|
|
583
655
|
|
|
@@ -588,42 +660,45 @@ function AppLauncherTab({ isMobile }: AppLauncherTabProps) {
|
|
|
588
660
|
path,
|
|
589
661
|
name: navItem.name,
|
|
590
662
|
displayName: navItem.displayName || navItem.name,
|
|
591
|
-
iconClassName: navItem.iconClassName ||
|
|
663
|
+
iconClassName: navItem.iconClassName || "bi-box-seam",
|
|
592
664
|
};
|
|
593
|
-
})
|
|
594
|
-
);
|
|
665
|
+
});
|
|
666
|
+
});
|
|
595
667
|
|
|
596
668
|
// Filter apps based on search term
|
|
597
669
|
const filteredApps = searchTerm.trim()
|
|
598
|
-
? allApps.filter(
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
670
|
+
? allApps.filter(
|
|
671
|
+
(app) =>
|
|
672
|
+
app.name.toLowerCase().includes(searchTerm.toLowerCase()) ||
|
|
673
|
+
app.displayName.toLowerCase().includes(searchTerm.toLowerCase()),
|
|
674
|
+
)
|
|
602
675
|
: allApps;
|
|
603
676
|
|
|
604
677
|
// Categorize filtered apps by package ID
|
|
605
|
-
const systemApps = filteredApps.filter(app => app.packageId ===
|
|
606
|
-
const userApps = filteredApps.filter(app => app.packageId !==
|
|
678
|
+
const systemApps = filteredApps.filter((app) => app.packageId === "system-apps");
|
|
679
|
+
const userApps = filteredApps.filter((app) => app.packageId !== "system-apps");
|
|
607
680
|
|
|
608
681
|
// Get recently used apps by matching paths (only show if they match search)
|
|
609
682
|
const recentAppItems = recentApps
|
|
610
|
-
.map(path => filteredApps.find(app => app.path === path))
|
|
683
|
+
.map((path) => filteredApps.find((app) => app.path === path))
|
|
611
684
|
.filter(Boolean) as AppItem[];
|
|
612
685
|
|
|
613
686
|
const openApp = (appItem: AppItem) => {
|
|
614
687
|
// Check if this is the mobile-settings app and we're in React Native
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
688
|
+
const w = window as Window & {
|
|
689
|
+
__NATIVE_THEME?: unknown;
|
|
690
|
+
ReactNativeWebView?: { postMessage: (message: string) => void };
|
|
691
|
+
};
|
|
692
|
+
if (appItem.path === "mobile-settings" && typeof w.__NATIVE_THEME !== "undefined") {
|
|
693
|
+
if (w.ReactNativeWebView) {
|
|
694
|
+
w.ReactNativeWebView.postMessage(
|
|
695
|
+
JSON.stringify({
|
|
696
|
+
type: "navigate",
|
|
697
|
+
path: "mobile-settings",
|
|
698
|
+
}),
|
|
699
|
+
);
|
|
624
700
|
} else {
|
|
625
|
-
|
|
626
|
-
window.location.href = 'peers://mobile-settings';
|
|
701
|
+
window.location.href = "peers://mobile-settings";
|
|
627
702
|
}
|
|
628
703
|
return;
|
|
629
704
|
}
|
|
@@ -631,17 +706,23 @@ function AppLauncherTab({ isMobile }: AppLauncherTabProps) {
|
|
|
631
706
|
};
|
|
632
707
|
|
|
633
708
|
return (
|
|
634
|
-
<div
|
|
709
|
+
<div
|
|
710
|
+
className={`container-fluid ${isMobile ? "p-2" : "p-4"}`}
|
|
711
|
+
style={{ maxHeight: "100%", overflowY: "auto" }}
|
|
712
|
+
>
|
|
635
713
|
{/* Search Bar */}
|
|
636
|
-
<div className={isMobile ?
|
|
714
|
+
<div className={isMobile ? "mb-3" : "mb-4"}>
|
|
637
715
|
<div className="position-relative">
|
|
638
|
-
<i
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
716
|
+
<i
|
|
717
|
+
className="bi-search position-absolute"
|
|
718
|
+
style={{
|
|
719
|
+
left: "12px",
|
|
720
|
+
top: "50%",
|
|
721
|
+
transform: "translateY(-50%)",
|
|
722
|
+
color: "#6c757d",
|
|
723
|
+
zIndex: 1,
|
|
724
|
+
}}
|
|
725
|
+
/>
|
|
645
726
|
<input
|
|
646
727
|
type="text"
|
|
647
728
|
className="form-control"
|
|
@@ -649,22 +730,23 @@ function AppLauncherTab({ isMobile }: AppLauncherTabProps) {
|
|
|
649
730
|
value={searchTerm}
|
|
650
731
|
onChange={(e) => setSearchTerm(e.target.value)}
|
|
651
732
|
style={{
|
|
652
|
-
paddingLeft:
|
|
653
|
-
fontSize: isMobile ?
|
|
733
|
+
paddingLeft: "40px",
|
|
734
|
+
fontSize: isMobile ? "14px" : "15px",
|
|
654
735
|
}}
|
|
655
736
|
/>
|
|
656
737
|
{searchTerm && (
|
|
657
738
|
<button
|
|
739
|
+
type="button"
|
|
658
740
|
className="btn btn-sm position-absolute"
|
|
659
741
|
style={{
|
|
660
|
-
right:
|
|
661
|
-
top:
|
|
662
|
-
transform:
|
|
663
|
-
border:
|
|
664
|
-
background:
|
|
665
|
-
color:
|
|
742
|
+
right: "8px",
|
|
743
|
+
top: "50%",
|
|
744
|
+
transform: "translateY(-50%)",
|
|
745
|
+
border: "none",
|
|
746
|
+
background: "none",
|
|
747
|
+
color: "#6c757d",
|
|
666
748
|
}}
|
|
667
|
-
onClick={() => setSearchTerm(
|
|
749
|
+
onClick={() => setSearchTerm("")}
|
|
668
750
|
>
|
|
669
751
|
<i className="bi-x" />
|
|
670
752
|
</button>
|
|
@@ -718,14 +800,22 @@ interface AppSectionProps {
|
|
|
718
800
|
|
|
719
801
|
function AppSection({ title, iconClassName, apps, onOpenApp, isMobile }: AppSectionProps) {
|
|
720
802
|
return (
|
|
721
|
-
<div className=
|
|
722
|
-
<h4 className={`${isMobile ?
|
|
803
|
+
<div className="mb-5">
|
|
804
|
+
<h4 className={`${isMobile ? "mb-3 h5" : "mb-3"}`}>
|
|
723
805
|
<i className={`${iconClassName} me-2`} />
|
|
724
806
|
{title}
|
|
725
807
|
</h4>
|
|
726
|
-
<div
|
|
727
|
-
{
|
|
728
|
-
|
|
808
|
+
<div
|
|
809
|
+
className={`d-flex flex-wrap ${isMobile ? "gap-3" : "gap-4"}`}
|
|
810
|
+
style={{ gap: isMobile ? "16px" : "20px" }}
|
|
811
|
+
>
|
|
812
|
+
{apps.map((app) => (
|
|
813
|
+
<AppCard
|
|
814
|
+
key={`${app.packageId}-${app.path}`}
|
|
815
|
+
appItem={app}
|
|
816
|
+
onOpenApp={onOpenApp}
|
|
817
|
+
isMobile={isMobile}
|
|
818
|
+
/>
|
|
729
819
|
))}
|
|
730
820
|
</div>
|
|
731
821
|
</div>
|
|
@@ -741,63 +831,64 @@ interface AppCardProps {
|
|
|
741
831
|
function AppCard({ appItem, onOpenApp, isMobile }: AppCardProps) {
|
|
742
832
|
const [_colorMode] = useObservable(colorMode);
|
|
743
833
|
|
|
744
|
-
const isDark = _colorMode ===
|
|
834
|
+
const isDark = _colorMode === "dark";
|
|
745
835
|
|
|
746
836
|
return (
|
|
747
837
|
<button
|
|
838
|
+
type="button"
|
|
748
839
|
className="d-flex flex-column align-items-center text-center"
|
|
749
840
|
style={{
|
|
750
|
-
cursor:
|
|
751
|
-
width: isMobile ?
|
|
752
|
-
transition:
|
|
753
|
-
background:
|
|
754
|
-
border:
|
|
841
|
+
cursor: "pointer",
|
|
842
|
+
width: isMobile ? "80px" : "90px",
|
|
843
|
+
transition: "all 0.15s ease",
|
|
844
|
+
background: "none",
|
|
845
|
+
border: "none",
|
|
755
846
|
padding: 0,
|
|
756
847
|
}}
|
|
757
848
|
title={appItem.name}
|
|
758
849
|
onMouseEnter={(e) => {
|
|
759
|
-
e.currentTarget.style.transform =
|
|
850
|
+
e.currentTarget.style.transform = "scale(1.05)";
|
|
760
851
|
}}
|
|
761
852
|
onMouseLeave={(e) => {
|
|
762
|
-
e.currentTarget.style.transform =
|
|
853
|
+
e.currentTarget.style.transform = "scale(1)";
|
|
763
854
|
}}
|
|
764
855
|
onClick={() => onOpenApp(appItem)}
|
|
765
856
|
>
|
|
766
857
|
<div
|
|
767
858
|
className="d-flex align-items-center justify-content-center mb-2"
|
|
768
859
|
style={{
|
|
769
|
-
width: isMobile ?
|
|
770
|
-
height: isMobile ?
|
|
771
|
-
backgroundColor: isDark ?
|
|
772
|
-
borderRadius:
|
|
773
|
-
border: `1px solid ${isDark ?
|
|
774
|
-
boxShadow: isDark ?
|
|
775
|
-
transition:
|
|
860
|
+
width: isMobile ? "64px" : "72px",
|
|
861
|
+
height: isMobile ? "64px" : "72px",
|
|
862
|
+
backgroundColor: isDark ? "#343a40" : "#f8f9fa",
|
|
863
|
+
borderRadius: "12px",
|
|
864
|
+
border: `1px solid ${isDark ? "#495057" : "#e9ecef"}`,
|
|
865
|
+
boxShadow: isDark ? "0 2px 4px rgba(0,0,0,0.3)" : "0 2px 4px rgba(0,0,0,0.08)",
|
|
866
|
+
transition: "all 0.15s ease",
|
|
776
867
|
}}
|
|
777
868
|
>
|
|
778
869
|
<i
|
|
779
870
|
className={appItem.iconClassName}
|
|
780
871
|
style={{
|
|
781
|
-
fontSize: isMobile ?
|
|
782
|
-
color: isDark ?
|
|
872
|
+
fontSize: isMobile ? "28px" : "32px",
|
|
873
|
+
color: isDark ? "#0d6efd" : "#0d6efd",
|
|
783
874
|
}}
|
|
784
875
|
/>
|
|
785
876
|
</div>
|
|
786
877
|
|
|
787
878
|
<span
|
|
788
|
-
className={isDark ?
|
|
879
|
+
className={isDark ? "text-light" : "text-dark"}
|
|
789
880
|
style={{
|
|
790
|
-
fontSize: isMobile ?
|
|
791
|
-
fontWeight:
|
|
792
|
-
lineHeight:
|
|
793
|
-
maxWidth:
|
|
794
|
-
overflow:
|
|
795
|
-
textOverflow:
|
|
796
|
-
whiteSpace:
|
|
881
|
+
fontSize: isMobile ? "11px" : "12px",
|
|
882
|
+
fontWeight: "500",
|
|
883
|
+
lineHeight: "1.2",
|
|
884
|
+
maxWidth: "100%",
|
|
885
|
+
overflow: "hidden",
|
|
886
|
+
textOverflow: "ellipsis",
|
|
887
|
+
whiteSpace: "nowrap",
|
|
797
888
|
}}
|
|
798
889
|
>
|
|
799
890
|
{appItem.displayName}
|
|
800
891
|
</span>
|
|
801
892
|
</button>
|
|
802
893
|
);
|
|
803
|
-
}
|
|
894
|
+
}
|