├── .dockerignore
├── .editorconfig
├── .github
├── ISSUE_TEMPLATE
│ ├── accessibility.md
│ ├── broken.md
│ └── config.yml
└── workflows
│ ├── e2e-tests-readonly.yml
│ ├── e2e-tests-readwrite.yml
│ └── unit-tests.yml
├── .gitignore
├── .husky
├── .gitignore
└── pre-commit
├── .testcaferc.json
├── .vercelignore
├── BREAKING_CHANGES.md
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── README.md
├── bin
├── backup-mastodon-data.sh
├── browser-shim.js
├── build-assets.js
├── build-inline-script.js
├── build-sass.js
├── build-svg.js
├── build-template-html.js
├── build-vercel-json.js
├── clone-mastodon.js
├── copy-vercel-json.sh
├── getIntl.js
├── install-mastodon.js
├── mastodon-config.js
├── mastodon-data.js
├── print-export-info.js
├── restore-mastodon-data.js
├── run-mastodon.js
├── svgs.js
├── terserOptions.js
├── test-vercel-json-unchanged.sh
├── wait-for-mastodon-data.js
└── wait-for-mastodon-to-start.js
├── docker-compose.yml
├── docs
├── Admin-Guide.md
├── Architecture.md
├── Internationalization.md
├── Screenshot1.png
├── Screenshot2.png
├── Screenshot3.png
├── Screenshot4.png
├── Screenshot5.png
├── Screenshot6.png
├── Theming.md
└── User-Guide.md
├── package.json
├── server.js
├── src
├── build
│ ├── manifest.json
│ └── template.html
├── client.js
├── inline-script
│ └── inline-script.js
├── intl
│ ├── de.js
│ ├── en-US.js
│ ├── es.js
│ ├── fr.js
│ └── ru-RU.JS
├── routes
│ ├── _a11y
│ │ ├── getAccessibleLabelForStatus.js
│ │ └── getAccountAccessibleName.js
│ ├── _actions
│ │ ├── accounts.js
│ │ ├── addInstance.js
│ │ ├── addStatusOrNotification.js
│ │ ├── autosuggest.js
│ │ ├── autosuggestAccountSearch.js
│ │ ├── autosuggestEmojiSearch.js
│ │ ├── autosuggestHashtagSearch.js
│ │ ├── block.js
│ │ ├── bookmark.js
│ │ ├── compose.js
│ │ ├── composePoll.js
│ │ ├── contentWarnings.js
│ │ ├── copyText.js
│ │ ├── createMakeProps.js
│ │ ├── delete.js
│ │ ├── deleteAndRedraft.js
│ │ ├── deleteStatuses.js
│ │ ├── doQuickLoginIfNecessary.js
│ │ ├── emoji.js
│ │ ├── favorite.js
│ │ ├── filters.js
│ │ ├── follow.js
│ │ ├── followRequests.js
│ │ ├── getRecentStatusesForAccount.js
│ │ ├── goToSearch.js
│ │ ├── instances.js
│ │ ├── lists.js
│ │ ├── media.js
│ │ ├── mention.js
│ │ ├── mute.js
│ │ ├── muteConversation.js
│ │ ├── onUserIsLoggedOut.js
│ │ ├── pin.js
│ │ ├── pinnedStatuses.js
│ │ ├── polls.js
│ │ ├── postPrivacy.js
│ │ ├── pushSubscription.js
│ │ ├── reblog.js
│ │ ├── rehydrateStatusOrNotification.js
│ │ ├── report.js
│ │ ├── reportStatuses.js
│ │ ├── requests.js
│ │ ├── search.js
│ │ ├── setAccountNotified.js
│ │ ├── setDomainBlocked.js
│ │ ├── setShowReblogs.js
│ │ ├── share.js
│ │ ├── showComposeDialog.js
│ │ ├── showMoreAndScrollToTop.js
│ │ ├── statuses.js
│ │ ├── stream
│ │ │ ├── fillStreamingGap.js
│ │ │ ├── processMessage.js
│ │ │ └── streaming.js
│ │ ├── timeline.js
│ │ ├── toggleMute.js
│ │ └── updateStatus.js
│ ├── _api
│ │ ├── block.js
│ │ ├── blockDomain.js
│ │ ├── blockedAndMuted.js
│ │ ├── bookmark.js
│ │ ├── delete.js
│ │ ├── emoji.js
│ │ ├── favorite.js
│ │ ├── filters.js
│ │ ├── follow.js
│ │ ├── followRequests.js
│ │ ├── followsAndFollowers.js
│ │ ├── instance.js
│ │ ├── lists.js
│ │ ├── media.js
│ │ ├── mute.js
│ │ ├── muteConversation.js
│ │ ├── notify.js
│ │ ├── oauth.js
│ │ ├── pin.js
│ │ ├── pinnedStatuses.js
│ │ ├── polls.js
│ │ ├── pushSubscription.js
│ │ ├── reblog.js
│ │ ├── reblogsAndFavs.js
│ │ ├── relationships.js
│ │ ├── report.js
│ │ ├── requests.js
│ │ ├── search.js
│ │ ├── showReblogs.js
│ │ ├── statuses.js
│ │ ├── stream
│ │ │ ├── TimelineStream.js
│ │ │ └── getStreamUrl.js
│ │ ├── timelines.js
│ │ ├── updateCredentials.js
│ │ ├── user.js
│ │ └── utils.js
│ ├── _components
│ │ ├── AccountsListPage.html
│ │ ├── AutoplayVideo.html
│ │ ├── Avatar.html
│ │ ├── Draggable.html
│ │ ├── DynamicHeading.html
│ │ ├── DynamicPageBanner.html
│ │ ├── ExternalLink.html
│ │ ├── FocusRestoration.html
│ │ ├── FreeTextLayout.html
│ │ ├── HiddenFromSSR.html
│ │ ├── IconButton.html
│ │ ├── InfoAside.html
│ │ ├── InformationalFooter.html
│ │ ├── Label.html
│ │ ├── LazyImage.html
│ │ ├── LazyPage.html
│ │ ├── LengthGauge.html
│ │ ├── LengthIndicator.html
│ │ ├── LoadingMask.html
│ │ ├── LoadingPage.html
│ │ ├── LoadingSpinner.html
│ │ ├── MediaControlsFix.html
│ │ ├── Nav.html
│ │ ├── NavItem.html
│ │ ├── NavItemIcon.html
│ │ ├── NavShortcuts.html
│ │ ├── NonAutoplayGifv.html
│ │ ├── NonAutoplayImg.html
│ │ ├── NotLoggedInHome.html
│ │ ├── NotificationFilters.html
│ │ ├── PlayVideoIcon.html
│ │ ├── Select.html
│ │ ├── ShortcutHelpInfo.html
│ │ ├── SvgIcon.html
│ │ ├── TabSet.html
│ │ ├── TimelineHomePage.html
│ │ ├── TimelinePage.html
│ │ ├── Title.html
│ │ ├── Tooltip.html
│ │ ├── community
│ │ │ ├── PageList.html
│ │ │ └── PageListItem.html
│ │ ├── compose
│ │ │ ├── ComposeAuthor.html
│ │ │ ├── ComposeAutosuggest.html
│ │ │ ├── ComposeAutosuggestContainer.html
│ │ │ ├── ComposeAutosuggestionList.html
│ │ │ ├── ComposeBox.html
│ │ │ ├── ComposeButton.html
│ │ │ ├── ComposeContentWarning.html
│ │ │ ├── ComposeFileDrop.html
│ │ │ ├── ComposeInput.html
│ │ │ ├── ComposeLengthGauge.html
│ │ │ ├── ComposeLengthIndicator.html
│ │ │ ├── ComposeMedia.html
│ │ │ ├── ComposeMediaItem.html
│ │ │ ├── ComposeMediaSensitive.html
│ │ │ ├── ComposePoll.html
│ │ │ ├── ComposeStickyButton.html
│ │ │ ├── ComposeToolbar.html
│ │ │ ├── LazyComposeBox.html
│ │ │ └── constants.js
│ │ ├── dialog
│ │ │ ├── asyncDialogs
│ │ │ │ ├── importShowAccountProfileOptionsDialog.js
│ │ │ │ ├── importShowComposeDialog.js
│ │ │ │ ├── importShowCopyDialog.js
│ │ │ │ ├── importShowEmojiDialog.js
│ │ │ │ ├── importShowMediaDialog.js
│ │ │ │ ├── importShowMediaEditDialog.js
│ │ │ │ ├── importShowMuteDialog.js
│ │ │ │ ├── importShowPostPrivacyDialog.js
│ │ │ │ ├── importShowReportDialog.js
│ │ │ │ ├── importShowShortcutHelpDialog.js
│ │ │ │ ├── importShowStatusOptionsDialog.js
│ │ │ │ ├── importShowTextConfirmationDialog.js
│ │ │ │ └── importShowWordFilterDialog.js
│ │ │ ├── components
│ │ │ │ ├── AccountProfileOptionsDialog.html
│ │ │ │ ├── ComposeDialog.html
│ │ │ │ ├── ConfirmationDialog.html
│ │ │ │ ├── CopyDialog.html
│ │ │ │ ├── EmojiDialog.html
│ │ │ │ ├── GenericConfirmationDialog.html
│ │ │ │ ├── GenericDialogList.html
│ │ │ │ ├── MediaAltEditor.html
│ │ │ │ ├── MediaDialog.html
│ │ │ │ ├── MediaEditDialog.html
│ │ │ │ ├── MediaFocalPointEditor.html
│ │ │ │ ├── MediaInDialog.html
│ │ │ │ ├── ModalDialog.html
│ │ │ │ ├── MuteDialog.html
│ │ │ │ ├── PinchZoomable.html
│ │ │ │ ├── PostPrivacyDialog.html
│ │ │ │ ├── ReportDialog.html
│ │ │ │ ├── ShortcutHelpDialog.html
│ │ │ │ ├── StatusOptionsDialog.html
│ │ │ │ ├── TextConfirmationDialog.html
│ │ │ │ └── WordFilterDialog.html
│ │ │ ├── creators
│ │ │ │ ├── showAccountProfileOptionsDialog.js
│ │ │ │ ├── showComposeDialog.js
│ │ │ │ ├── showCopyDialog.js
│ │ │ │ ├── showDialog.js
│ │ │ │ ├── showEmojiDialog.js
│ │ │ │ ├── showMediaDialog.js
│ │ │ │ ├── showMediaEditDialog.js
│ │ │ │ ├── showMuteDialog.js
│ │ │ │ ├── showPostPrivacyDialog.js
│ │ │ │ ├── showReportDialog.js
│ │ │ │ ├── showShortcutHelpDialog.js
│ │ │ │ ├── showStatusOptionsDialog.js
│ │ │ │ ├── showTextConfirmationDialog.js
│ │ │ │ └── showWordFilterDialog.js
│ │ │ └── helpers
│ │ │ │ ├── closeDialog.js
│ │ │ │ ├── createDialogElement.js
│ │ │ │ ├── createDialogId.js
│ │ │ │ ├── onCreateDialog.js
│ │ │ │ └── showDialog.js
│ │ ├── list
│ │ │ ├── List.html
│ │ │ ├── ListItem.html
│ │ │ ├── ListLazyItem.html
│ │ │ └── listStore.js
│ │ ├── profile
│ │ │ ├── AccountDisplayName.html
│ │ │ ├── AccountProfile.html
│ │ │ ├── AccountProfileDetails.html
│ │ │ ├── AccountProfileFilters.html
│ │ │ ├── AccountProfileFollow.html
│ │ │ ├── AccountProfileHeader.html
│ │ │ ├── AccountProfileMeta.html
│ │ │ ├── AccountProfileMovedBanner.html
│ │ │ ├── AccountProfileNote.html
│ │ │ └── AccountProfilePage.html
│ │ ├── radio
│ │ │ ├── RadioGroup.html
│ │ │ └── RadioGroupButton.html
│ │ ├── search
│ │ │ ├── AccountSearchResult.html
│ │ │ ├── HashtagSearchResult.html
│ │ │ ├── Search.html
│ │ │ ├── SearchResult.html
│ │ │ ├── SearchResults.html
│ │ │ └── StatusSearchResult.html
│ │ ├── settings
│ │ │ ├── SettingsLayout.html
│ │ │ ├── SettingsList.html
│ │ │ ├── SettingsListButton.html
│ │ │ ├── SettingsListRow.html
│ │ │ ├── SettingsNav.html
│ │ │ ├── SettingsNavItem.html
│ │ │ ├── UISettingsStyles.html
│ │ │ └── instance
│ │ │ │ ├── GenericInstanceSettings.html
│ │ │ │ ├── GenericInstanceSettingsStyle.html
│ │ │ │ ├── HomeTimelineFilterSettings.html
│ │ │ │ ├── InstanceActions.html
│ │ │ │ ├── InstanceUserProfile.html
│ │ │ │ ├── NotificationFilterSettings.html
│ │ │ │ ├── PushNotificationSettings.html
│ │ │ │ ├── ThemeSettings.html
│ │ │ │ └── WordFilterSettings.html
│ │ ├── shortcut
│ │ │ ├── ScrollListShortcuts.html
│ │ │ └── Shortcut.html
│ │ ├── snackbar
│ │ │ ├── Snackbar.html
│ │ │ └── snackbar.js
│ │ ├── status
│ │ │ ├── Media.html
│ │ │ ├── MediaAttachments.html
│ │ │ ├── Notification.html
│ │ │ ├── Status.html
│ │ │ ├── StatusAuthorHandle.html
│ │ │ ├── StatusAuthorName.html
│ │ │ ├── StatusCard.html
│ │ │ ├── StatusComposeBox.html
│ │ │ ├── StatusContent.html
│ │ │ ├── StatusDetails.html
│ │ │ ├── StatusHeader.html
│ │ │ ├── StatusMediaAttachments.html
│ │ │ ├── StatusMentions.html
│ │ │ ├── StatusPoll.html
│ │ │ ├── StatusRelativeDate.html
│ │ │ ├── StatusSidebar.html
│ │ │ ├── StatusSpoiler.html
│ │ │ └── StatusToolbar.html
│ │ ├── timeline
│ │ │ ├── LazyTimeline.html
│ │ │ ├── LoadingFooter.html
│ │ │ ├── MoreHeader.html
│ │ │ ├── MoreHeaderVirtualWrapper.html
│ │ │ ├── NotificationVirtualListItem.html
│ │ │ ├── PinnedStatuses.html
│ │ │ ├── StatusVirtualListItem.html
│ │ │ └── Timeline.html
│ │ ├── toast
│ │ │ ├── Toast.html
│ │ │ └── toast.js
│ │ └── virtualList
│ │ │ ├── VirtualList.html
│ │ │ ├── VirtualListContainer.html
│ │ │ ├── VirtualListFooter.html
│ │ │ ├── VirtualListHeader.html
│ │ │ ├── VirtualListItem.html
│ │ │ ├── VirtualListLazyItem.html
│ │ │ └── virtualListStore.js
│ ├── _database
│ │ ├── accounts.js
│ │ ├── asyncDatabase.js
│ │ ├── cache.js
│ │ ├── cleanup.js
│ │ ├── clear.js
│ │ ├── constants.js
│ │ ├── database.js
│ │ ├── databaseApis.js
│ │ ├── databaseLifecycle.js
│ │ ├── helpers.js
│ │ ├── keys.js
│ │ ├── knownInstances.js
│ │ ├── mediaUploadFileCache.js
│ │ ├── meta.js
│ │ ├── migrations.js
│ │ ├── relationships.js
│ │ ├── timelines
│ │ │ ├── cacheStatus.js
│ │ │ ├── deletion.js
│ │ │ ├── fetchAccount.js
│ │ │ ├── fetchNotification.js
│ │ │ ├── fetchStatus.js
│ │ │ ├── getStatusOrNotification.js
│ │ │ ├── insertion.js
│ │ │ ├── lookup.js
│ │ │ ├── pagination.js
│ │ │ ├── pinnedStatuses.js
│ │ │ └── updateStatus.js
│ │ ├── utils.js
│ │ └── webShare.js
│ ├── _error.html
│ ├── _intl
│ │ └── formatTimeagoDate.js
│ ├── _layout.html
│ ├── _pages
│ │ ├── accounts
│ │ │ └── [accountId]
│ │ │ │ ├── followers.html
│ │ │ │ ├── follows.html
│ │ │ │ ├── index.html
│ │ │ │ ├── media.html
│ │ │ │ └── with_replies.html
│ │ ├── blocked.html
│ │ ├── bookmarks.html
│ │ ├── community
│ │ │ └── index.html
│ │ ├── direct.html
│ │ ├── favorites.html
│ │ ├── federated.html
│ │ ├── index.html
│ │ ├── lists
│ │ │ └── [listId].html
│ │ ├── local.html
│ │ ├── muted.html
│ │ ├── notifications
│ │ │ ├── index.html
│ │ │ └── mentions.html
│ │ ├── pinned.html
│ │ ├── requests.html
│ │ ├── search.html
│ │ ├── settings
│ │ │ ├── about.html
│ │ │ ├── general.html
│ │ │ ├── hotkeys.html
│ │ │ ├── index.html
│ │ │ ├── instances
│ │ │ │ ├── [instanceName].html
│ │ │ │ ├── add.html
│ │ │ │ └── index.html
│ │ │ └── wellness.html
│ │ ├── statuses
│ │ │ └── [statusId]
│ │ │ │ ├── favorites.html
│ │ │ │ ├── index.html
│ │ │ │ └── reblogs.html
│ │ └── tags
│ │ │ └── [tagName].html
│ ├── _static
│ │ ├── animations.js
│ │ ├── autosuggest.js
│ │ ├── blocks.js
│ │ ├── blurhash.js
│ │ ├── database.js
│ │ ├── emojiPickerIntl.js
│ │ ├── fonts.js
│ │ ├── instanceSettings.js
│ │ ├── intl.js
│ │ ├── media.js
│ │ ├── pages.js
│ │ ├── polls.js
│ │ ├── share.js
│ │ ├── statuses.js
│ │ ├── themes.js
│ │ ├── timelines.js
│ │ └── wordFilters.js
│ ├── _store
│ │ ├── LocalStorageStore.js
│ │ ├── computations
│ │ │ ├── autosuggestComputations.js
│ │ │ ├── badgeComputations.js
│ │ │ ├── computations.js
│ │ │ ├── instanceComputations.js
│ │ │ ├── loggedInComputations.js
│ │ │ ├── navComputations.js
│ │ │ ├── timelineComputations.js
│ │ │ ├── timelineFilterComputations.js
│ │ │ └── wordFilterComputations.js
│ │ ├── loggedInStoreExtensions.js
│ │ ├── mixins
│ │ │ ├── autosuggestMixins.js
│ │ │ ├── composeMixins.js
│ │ │ ├── instanceMixins.js
│ │ │ ├── loggedInMixins.js
│ │ │ ├── mixins.js
│ │ │ ├── statusMixins.js
│ │ │ └── timelineMixins.js
│ │ ├── observers
│ │ │ ├── autosuggestObservers.js
│ │ │ ├── badgeObservers.js
│ │ │ ├── bottomNavObservers.js
│ │ │ ├── centerNavObservers.js
│ │ │ ├── cleanup.js
│ │ │ ├── countryFlagEmojiPolyfill.js
│ │ │ ├── customEmojiObservers.js
│ │ │ ├── customScrollbarObservers.js
│ │ │ ├── focusRingObservers.js
│ │ │ ├── grayscaleObservers.js
│ │ │ ├── instanceObservers.js
│ │ │ ├── leftRightFocusObservers.js
│ │ │ ├── logOutObservers.js
│ │ │ ├── loggedInObservers.js
│ │ │ ├── navObservers.js
│ │ │ ├── notificationObservers.js
│ │ │ ├── notificationPermissionObservers.js
│ │ │ ├── nowObservers.js
│ │ │ ├── observers.js
│ │ │ ├── onlineObservers.js
│ │ │ ├── pageVisibilityObservers.js
│ │ │ ├── resizeObservers.js
│ │ │ ├── setupLoggedInObservers.js
│ │ │ ├── showComposeDialogObservers.js
│ │ │ ├── timelineObservers.js
│ │ │ ├── touchObservers.js
│ │ │ └── wordFilterObservers.js
│ │ ├── store.js
│ │ └── storeLite.js
│ ├── _thirdparty
│ │ ├── a11y-dialog
│ │ │ ├── LICENSE
│ │ │ └── a11y-dialog.js
│ │ ├── autosize
│ │ │ ├── LICENSE.md
│ │ │ └── autosize.js
│ │ ├── idb-keyval
│ │ │ ├── LICENCE
│ │ │ └── idb-keyval.js
│ │ ├── intrinsic-scale
│ │ │ ├── LICENSE
│ │ │ └── intrinsicScale.js
│ │ ├── large-small-dynamic-viewport-units-polyfill
│ │ │ ├── LICENSE
│ │ │ └── dynamic-viewport-utils-polyfill.js
│ │ ├── lodash
│ │ │ ├── LICENSE
│ │ │ ├── objects.js
│ │ │ ├── objects.src.js
│ │ │ ├── rollup.config.js
│ │ │ ├── timers.js
│ │ │ └── timers.src.js
│ │ ├── quick-lru
│ │ │ ├── license
│ │ │ └── quick-lru.js
│ │ ├── timeago
│ │ │ ├── LICENSE
│ │ │ └── timeago.js
│ │ ├── unescape
│ │ │ ├── LICENSE
│ │ │ └── unescape.js
│ │ └── websocket
│ │ │ ├── LICENSE
│ │ │ ├── backoff.js
│ │ │ └── websocket.js
│ ├── _transitions
│ │ └── slide.js
│ ├── _utils
│ │ ├── PromiseThrottler.js
│ │ ├── RealmStore.js
│ │ ├── RequestThrottler.js
│ │ ├── addEmojiTooltips.js
│ │ ├── ajax.js
│ │ ├── animate.js
│ │ ├── announceAriaLivePolite.js
│ │ ├── arrays.js
│ │ ├── asyncModules
│ │ │ ├── importArrowKeyNavigation.js
│ │ │ ├── importComposeBox.js
│ │ │ ├── importDatabase.js
│ │ │ ├── importEmojiMart.js
│ │ │ ├── importList.js
│ │ │ ├── importLoggedInStoreExtensions.js
│ │ │ ├── importNavShortcuts.js
│ │ │ ├── importNotificationVirtualListItem.js
│ │ │ ├── importPageLifecycle.js
│ │ │ ├── importSnackbar.js
│ │ │ ├── importStatusVirtualListItem.js
│ │ │ ├── importTesseractWorker.js
│ │ │ ├── importTimeline.js
│ │ │ ├── importToast.js
│ │ │ ├── importVirtualList.js
│ │ │ └── importVirtualListStore.js
│ │ ├── base64.js
│ │ ├── blurhash.js
│ │ ├── checkDomAncestors.js
│ │ ├── classname.js
│ │ ├── computeFilterContextsForStatusOrNotification.js
│ │ ├── convertCssPropertyToDataUrl.js
│ │ ├── convertCustomEmojiToEmojiPickerFormat.js
│ │ ├── coordsToPercent.js
│ │ ├── createAutosuggestAccessibleLabel.js
│ │ ├── createFilterFunction.js
│ │ ├── createPriorityQueue.js
│ │ ├── createRegexFromFilters.js
│ │ ├── createSearchIndexFromStatusOrNotification.js
│ │ ├── createStatusOrNotificationUuid.js
│ │ ├── decodeImage.js
│ │ ├── delegate.js
│ │ ├── doubleRAF.js
│ │ ├── emojiDatabase.js
│ │ ├── emojiRegex.js
│ │ ├── emojifyText.js
│ │ ├── eventBus.js
│ │ ├── events.js
│ │ ├── forceOnline.js
│ │ ├── formatIntl.js
│ │ ├── formatters.js
│ │ ├── fullscreen.js
│ │ ├── getIdFromItemSummaries.js
│ │ ├── getImageNativeDimensions.js
│ │ ├── handleRegex.js
│ │ ├── historyEvents.js
│ │ ├── isDarkTheme.js
│ │ ├── lifecycle.js
│ │ ├── loadCSS.js
│ │ ├── loadingMask.js
│ │ ├── lodash-lite.js
│ │ ├── maps.js
│ │ ├── marks.js
│ │ ├── massageStatusPlainText.js
│ │ ├── massageUserText.js
│ │ ├── measureText.js
│ │ ├── normalizePageName.js
│ │ ├── once.js
│ │ ├── pointerEvents.js
│ │ ├── polyfills
│ │ │ ├── asyncPolyfills.js
│ │ │ ├── loadNonCriticalPolyfills.js
│ │ │ └── loadPolyfills.js
│ │ ├── queueMicrotask.js
│ │ ├── removeEmoji.js
│ │ ├── replaceEmoji.js
│ │ ├── requestPostAnimationFrame.js
│ │ ├── reselect.js
│ │ ├── resize.js
│ │ ├── runMediumPriorityTask.js
│ │ ├── runTesseract.js
│ │ ├── safeLocalStorage.js
│ │ ├── safeParse.js
│ │ ├── scheduleIdleTask.js
│ │ ├── scheduleInterval.js
│ │ ├── scrollContainer.js
│ │ ├── scrollIntoView.js
│ │ ├── scrollToTop.js
│ │ ├── serviceWorkerClient.js
│ │ ├── setFavicon.js
│ │ ├── shortcuts.js
│ │ ├── smoothScroll.js
│ │ ├── sortItemSummariesForThread.js
│ │ ├── statusHtmlToPlainText.js
│ │ ├── statusIdSorting.js
│ │ ├── strings.js
│ │ ├── supportsFocusVisible.js
│ │ ├── supportsSelector.js
│ │ ├── sync.js
│ │ ├── tesseractWorker.js
│ │ ├── testEmojiSupported.js
│ │ ├── testStorage.js
│ │ ├── themeEngine.js
│ │ ├── throttleTimer.js
│ │ ├── thunk.js
│ │ ├── timelineItemToSummary.js
│ │ ├── tryToFocusElement.js
│ │ ├── urlIsCrossOrigin.js
│ │ ├── urlRegex.js
│ │ ├── urlRegexSource.js
│ │ └── userAgent
│ │ │ ├── isChrome.js
│ │ │ ├── isChromePre82.js
│ │ │ ├── isChromePre87.js
│ │ │ ├── isFirefoxPre90.js
│ │ │ ├── isIOS.js
│ │ │ ├── isIOSPre12Point2.js
│ │ │ ├── isIOSPre13.js
│ │ │ ├── isKaiOS.js
│ │ │ ├── isMac.js
│ │ │ ├── isMobile.js
│ │ │ └── isWebKit.js
│ ├── _workers
│ │ └── blurhash.js
│ ├── accounts
│ │ └── [accountId]
│ │ │ ├── followers.html
│ │ │ ├── follows.html
│ │ │ ├── index.html
│ │ │ ├── media.html
│ │ │ └── with_replies.html
│ ├── blocked.html
│ ├── bookmarks.html
│ ├── community
│ │ └── index.html
│ ├── direct.html
│ ├── favorites.html
│ ├── federated.html
│ ├── index.html
│ ├── lists
│ │ └── [listId].html
│ ├── local.html
│ ├── muted.html
│ ├── notifications
│ │ ├── index.html
│ │ └── mentions.html
│ ├── pinned.html
│ ├── requests.html
│ ├── search.html
│ ├── settings
│ │ ├── about.html
│ │ ├── general.html
│ │ ├── hotkeys.html
│ │ ├── index.html
│ │ ├── instances
│ │ │ ├── [instanceName].html
│ │ │ ├── add.html
│ │ │ └── index.html
│ │ └── wellness.html
│ ├── statuses
│ │ └── [statusId]
│ │ │ ├── favorites.html
│ │ │ ├── index.html
│ │ │ └── reblogs.html
│ └── tags
│ │ └── [tagName].html
├── scss
│ ├── custom-scrollbars.scss
│ ├── focus.scss
│ ├── fonts.scss
│ ├── global.scss
│ ├── themes
│ │ ├── _base.scss
│ │ ├── _dark.scss
│ │ ├── _dark_navbar.scss
│ │ ├── _dark_scrollbars.scss
│ │ ├── _default.scss
│ │ ├── _light_scrollbars.scss
│ │ ├── _scrollbars.scss
│ │ ├── cobalt.scss
│ │ ├── dark-grayscale.scss
│ │ ├── gecko.scss
│ │ ├── grayscale.scss
│ │ ├── hacker.scss
│ │ ├── hotpants.scss
│ │ ├── majesty.scss
│ │ ├── mastodon.scss
│ │ ├── oaken.scss
│ │ ├── ozark.scss
│ │ ├── pitchblack.scss
│ │ ├── punk.scss
│ │ ├── riot.scss
│ │ ├── scarlet.scss
│ │ ├── seafoam.scss
│ │ └── sorcery.scss
│ └── variables.scss
├── server.js
├── server
│ └── sapperInlineScriptChecksums.js
├── service-worker.js
├── static
│ ├── icon-shortcut-fa-bell.xcf
│ ├── icon-shortcut-fa-pencil.xcf
│ ├── logo.svg
│ ├── semaphore-logo-square.svg
│ └── semaphore-logo.svg
└── thirdparty
│ └── font-awesome-svg-png
│ ├── LICENSE
│ ├── README.md
│ └── white
│ └── svg
│ ├── 500px.svg
│ ├── address-book-o.svg
│ ├── address-book.svg
│ ├── address-card-o.svg
│ ├── address-card.svg
│ ├── adjust.svg
│ ├── adn.svg
│ ├── align-center.svg
│ ├── align-justify.svg
│ ├── align-left.svg
│ ├── align-right.svg
│ ├── amazon.svg
│ ├── ambulance.svg
│ ├── american-sign-language-interpreting.svg
│ ├── anchor.svg
│ ├── android.svg
│ ├── angellist.svg
│ ├── angle-double-down.svg
│ ├── angle-double-left.svg
│ ├── angle-double-right.svg
│ ├── angle-double-up.svg
│ ├── angle-down.svg
│ ├── angle-left.svg
│ ├── angle-right.svg
│ ├── angle-up.svg
│ ├── apple.svg
│ ├── archive.svg
│ ├── area-chart.svg
│ ├── arrow-circle-down.svg
│ ├── arrow-circle-left.svg
│ ├── arrow-circle-o-down.svg
│ ├── arrow-circle-o-left.svg
│ ├── arrow-circle-o-right.svg
│ ├── arrow-circle-o-up.svg
│ ├── arrow-circle-right.svg
│ ├── arrow-circle-up.svg
│ ├── arrow-down.svg
│ ├── arrow-left.svg
│ ├── arrow-right.svg
│ ├── arrow-up.svg
│ ├── arrows-alt.svg
│ ├── arrows-h.svg
│ ├── arrows-v.svg
│ ├── arrows.svg
│ ├── asl-interpreting.svg
│ ├── assistive-listening-systems.svg
│ ├── asterisk.svg
│ ├── at.svg
│ ├── audio-description.svg
│ ├── automobile.svg
│ ├── backward.svg
│ ├── balance-scale.svg
│ ├── ban.svg
│ ├── bandcamp.svg
│ ├── bank.svg
│ ├── bar-chart-o.svg
│ ├── bar-chart.svg
│ ├── barcode.svg
│ ├── bars.svg
│ ├── bath.svg
│ ├── bathtub.svg
│ ├── battery-0.svg
│ ├── battery-1.svg
│ ├── battery-2.svg
│ ├── battery-3.svg
│ ├── battery-4.svg
│ ├── battery-empty.svg
│ ├── battery-full.svg
│ ├── battery-half.svg
│ ├── battery-quarter.svg
│ ├── battery-three-quarters.svg
│ ├── battery.svg
│ ├── bed.svg
│ ├── beer.svg
│ ├── behance-square.svg
│ ├── behance.svg
│ ├── bell-o.svg
│ ├── bell-slash-o.svg
│ ├── bell-slash.svg
│ ├── bell.svg
│ ├── bicycle.svg
│ ├── binoculars.svg
│ ├── birthday-cake.svg
│ ├── bitbucket-square.svg
│ ├── bitbucket.svg
│ ├── bitcoin.svg
│ ├── black-tie.svg
│ ├── blind.svg
│ ├── bluetooth-b.svg
│ ├── bluetooth.svg
│ ├── bold.svg
│ ├── bolt.svg
│ ├── bomb.svg
│ ├── book.svg
│ ├── bookmark-o.svg
│ ├── bookmark.svg
│ ├── braille.svg
│ ├── briefcase.svg
│ ├── btc.svg
│ ├── bug.svg
│ ├── building-o.svg
│ ├── building.svg
│ ├── bullhorn.svg
│ ├── bullseye.svg
│ ├── bus.svg
│ ├── buysellads.svg
│ ├── cab.svg
│ ├── calculator.svg
│ ├── calendar-check-o.svg
│ ├── calendar-minus-o.svg
│ ├── calendar-o.svg
│ ├── calendar-plus-o.svg
│ ├── calendar-times-o.svg
│ ├── calendar.svg
│ ├── camera-retro.svg
│ ├── camera.svg
│ ├── car.svg
│ ├── caret-down.svg
│ ├── caret-left.svg
│ ├── caret-right.svg
│ ├── caret-square-o-down.svg
│ ├── caret-square-o-left.svg
│ ├── caret-square-o-right.svg
│ ├── caret-square-o-up.svg
│ ├── caret-up.svg
│ ├── cart-arrow-down.svg
│ ├── cart-plus.svg
│ ├── cc-amex.svg
│ ├── cc-diners-club.svg
│ ├── cc-discover.svg
│ ├── cc-jcb.svg
│ ├── cc-mastercard.svg
│ ├── cc-paypal.svg
│ ├── cc-stripe.svg
│ ├── cc-visa.svg
│ ├── cc.svg
│ ├── certificate.svg
│ ├── chain-broken.svg
│ ├── chain.svg
│ ├── check-circle-o.svg
│ ├── check-circle.svg
│ ├── check-square-o.svg
│ ├── check-square.svg
│ ├── check.svg
│ ├── chevron-circle-down.svg
│ ├── chevron-circle-left.svg
│ ├── chevron-circle-right.svg
│ ├── chevron-circle-up.svg
│ ├── chevron-down.svg
│ ├── chevron-left.svg
│ ├── chevron-right.svg
│ ├── chevron-up.svg
│ ├── child.svg
│ ├── chrome.svg
│ ├── circle-o-notch.svg
│ ├── circle-o.svg
│ ├── circle-thin.svg
│ ├── circle.svg
│ ├── clipboard.svg
│ ├── clock-o.svg
│ ├── clone.svg
│ ├── close.svg
│ ├── cloud-download.svg
│ ├── cloud-upload.svg
│ ├── cloud.svg
│ ├── cny.svg
│ ├── code-fork.svg
│ ├── code.svg
│ ├── codepen.svg
│ ├── codiepie.svg
│ ├── coffee.svg
│ ├── cog.svg
│ ├── cogs.svg
│ ├── columns.svg
│ ├── comment-o.svg
│ ├── comment.svg
│ ├── commenting-o.svg
│ ├── commenting.svg
│ ├── comments-o.svg
│ ├── comments.svg
│ ├── compass.svg
│ ├── compress.svg
│ ├── connectdevelop.svg
│ ├── contao.svg
│ ├── copy.svg
│ ├── copyright.svg
│ ├── creative-commons.svg
│ ├── credit-card-alt.svg
│ ├── credit-card.svg
│ ├── crop.svg
│ ├── crosshairs.svg
│ ├── css3.svg
│ ├── cube.svg
│ ├── cubes.svg
│ ├── cut.svg
│ ├── cutlery.svg
│ ├── dashboard.svg
│ ├── dashcube.svg
│ ├── database.svg
│ ├── deaf.svg
│ ├── deafness.svg
│ ├── dedent.svg
│ ├── delicious.svg
│ ├── desktop.svg
│ ├── deviantart.svg
│ ├── diamond.svg
│ ├── digg.svg
│ ├── dollar.svg
│ ├── dot-circle-o.svg
│ ├── download.svg
│ ├── dribbble.svg
│ ├── drivers-license-o.svg
│ ├── drivers-license.svg
│ ├── dropbox.svg
│ ├── drupal.svg
│ ├── edge.svg
│ ├── edit.svg
│ ├── eercast.svg
│ ├── eject.svg
│ ├── ellipsis-h.svg
│ ├── ellipsis-v.svg
│ ├── empire.svg
│ ├── envelope-o.svg
│ ├── envelope-open-o.svg
│ ├── envelope-open.svg
│ ├── envelope-square.svg
│ ├── envelope.svg
│ ├── envira.svg
│ ├── eraser.svg
│ ├── etsy.svg
│ ├── eur.svg
│ ├── euro.svg
│ ├── exchange.svg
│ ├── exclamation-circle.svg
│ ├── exclamation-triangle.svg
│ ├── exclamation.svg
│ ├── expand.svg
│ ├── expeditedssl.svg
│ ├── external-link-square.svg
│ ├── external-link.svg
│ ├── eye-slash.svg
│ ├── eye.svg
│ ├── eyedropper.svg
│ ├── fa.svg
│ ├── facebook-f.svg
│ ├── facebook-official.svg
│ ├── facebook-square.svg
│ ├── facebook.svg
│ ├── fast-backward.svg
│ ├── fast-forward.svg
│ ├── fax.svg
│ ├── feed.svg
│ ├── female.svg
│ ├── fighter-jet.svg
│ ├── file-archive-o.svg
│ ├── file-audio-o.svg
│ ├── file-code-o.svg
│ ├── file-excel-o.svg
│ ├── file-image-o.svg
│ ├── file-movie-o.svg
│ ├── file-o.svg
│ ├── file-pdf-o.svg
│ ├── file-photo-o.svg
│ ├── file-picture-o.svg
│ ├── file-powerpoint-o.svg
│ ├── file-sound-o.svg
│ ├── file-text-o.svg
│ ├── file-text.svg
│ ├── file-video-o.svg
│ ├── file-word-o.svg
│ ├── file-zip-o.svg
│ ├── file.svg
│ ├── files-o.svg
│ ├── film.svg
│ ├── filter.svg
│ ├── fire-extinguisher.svg
│ ├── fire.svg
│ ├── firefox.svg
│ ├── first-order.svg
│ ├── flag-checkered.svg
│ ├── flag-o.svg
│ ├── flag.svg
│ ├── flash.svg
│ ├── flask.svg
│ ├── flickr.svg
│ ├── floppy-o.svg
│ ├── folder-o.svg
│ ├── folder-open-o.svg
│ ├── folder-open.svg
│ ├── folder.svg
│ ├── font-awesome.svg
│ ├── font.svg
│ ├── fonticons.svg
│ ├── fort-awesome.svg
│ ├── forumbee.svg
│ ├── forward.svg
│ ├── foursquare.svg
│ ├── free-code-camp.svg
│ ├── frown-o.svg
│ ├── futbol-o.svg
│ ├── gamepad.svg
│ ├── gavel.svg
│ ├── gbp.svg
│ ├── ge.svg
│ ├── gear.svg
│ ├── gears.svg
│ ├── genderless.svg
│ ├── get-pocket.svg
│ ├── gg-circle.svg
│ ├── gg.svg
│ ├── gift.svg
│ ├── git-square.svg
│ ├── git.svg
│ ├── github-alt.svg
│ ├── github-square.svg
│ ├── github.svg
│ ├── gitlab.svg
│ ├── gittip.svg
│ ├── glass.svg
│ ├── glide-g.svg
│ ├── glide.svg
│ ├── globe.svg
│ ├── google-plus-circle.svg
│ ├── google-plus-official.svg
│ ├── google-plus-square.svg
│ ├── google-plus.svg
│ ├── google-wallet.svg
│ ├── google.svg
│ ├── graduation-cap.svg
│ ├── gratipay.svg
│ ├── grav.svg
│ ├── group.svg
│ ├── h-square.svg
│ ├── hacker-news.svg
│ ├── hand-grab-o.svg
│ ├── hand-lizard-o.svg
│ ├── hand-o-down.svg
│ ├── hand-o-left.svg
│ ├── hand-o-right.svg
│ ├── hand-o-up.svg
│ ├── hand-paper-o.svg
│ ├── hand-peace-o.svg
│ ├── hand-pointer-o.svg
│ ├── hand-rock-o.svg
│ ├── hand-scissors-o.svg
│ ├── hand-spock-o.svg
│ ├── hand-stop-o.svg
│ ├── handshake-o.svg
│ ├── hard-of-hearing.svg
│ ├── hashtag.svg
│ ├── hdd-o.svg
│ ├── header.svg
│ ├── headphones.svg
│ ├── heart-o.svg
│ ├── heart.svg
│ ├── heartbeat.svg
│ ├── history.svg
│ ├── home.svg
│ ├── hospital-o.svg
│ ├── hotel.svg
│ ├── hourglass-1.svg
│ ├── hourglass-2.svg
│ ├── hourglass-3.svg
│ ├── hourglass-end.svg
│ ├── hourglass-half.svg
│ ├── hourglass-o.svg
│ ├── hourglass-start.svg
│ ├── hourglass.svg
│ ├── houzz.svg
│ ├── html5.svg
│ ├── i-cursor.svg
│ ├── id-badge.svg
│ ├── id-card-o.svg
│ ├── id-card.svg
│ ├── ils.svg
│ ├── image.svg
│ ├── imdb.svg
│ ├── inbox.svg
│ ├── indent.svg
│ ├── industry.svg
│ ├── info-circle.svg
│ ├── info.svg
│ ├── inr.svg
│ ├── instagram.svg
│ ├── institution.svg
│ ├── internet-explorer.svg
│ ├── intersex.svg
│ ├── ioxhost.svg
│ ├── italic.svg
│ ├── joomla.svg
│ ├── jpy.svg
│ ├── jsfiddle.svg
│ ├── key.svg
│ ├── keyboard-o.svg
│ ├── krw.svg
│ ├── language.svg
│ ├── laptop.svg
│ ├── lastfm-square.svg
│ ├── lastfm.svg
│ ├── leaf.svg
│ ├── leanpub.svg
│ ├── legal.svg
│ ├── lemon-o.svg
│ ├── level-down.svg
│ ├── level-up.svg
│ ├── life-bouy.svg
│ ├── life-buoy.svg
│ ├── life-ring.svg
│ ├── life-saver.svg
│ ├── lightbulb-o.svg
│ ├── line-chart.svg
│ ├── link.svg
│ ├── linkedin-square.svg
│ ├── linkedin.svg
│ ├── linode.svg
│ ├── linux.svg
│ ├── list-alt.svg
│ ├── list-ol.svg
│ ├── list-ul.svg
│ ├── list.svg
│ ├── location-arrow.svg
│ ├── lock.svg
│ ├── long-arrow-down.svg
│ ├── long-arrow-left.svg
│ ├── long-arrow-right.svg
│ ├── long-arrow-up.svg
│ ├── low-vision.svg
│ ├── magic.svg
│ ├── magnet.svg
│ ├── mail-forward.svg
│ ├── mail-reply-all.svg
│ ├── mail-reply.svg
│ ├── male.svg
│ ├── map-marker.svg
│ ├── map-o.svg
│ ├── map-pin.svg
│ ├── map-signs.svg
│ ├── map.svg
│ ├── mars-double.svg
│ ├── mars-stroke-h.svg
│ ├── mars-stroke-v.svg
│ ├── mars-stroke.svg
│ ├── mars.svg
│ ├── maxcdn.svg
│ ├── meanpath.svg
│ ├── medium.svg
│ ├── medkit.svg
│ ├── meetup.svg
│ ├── meh-o.svg
│ ├── mercury.svg
│ ├── microchip.svg
│ ├── microphone-slash.svg
│ ├── microphone.svg
│ ├── minus-circle.svg
│ ├── minus-square-o.svg
│ ├── minus-square.svg
│ ├── minus.svg
│ ├── mixcloud.svg
│ ├── mobile-phone.svg
│ ├── mobile.svg
│ ├── modx.svg
│ ├── money.svg
│ ├── moon-o.svg
│ ├── mortar-board.svg
│ ├── motorcycle.svg
│ ├── mouse-pointer.svg
│ ├── music.svg
│ ├── navicon.svg
│ ├── neuter.svg
│ ├── newspaper-o.svg
│ ├── object-group.svg
│ ├── object-ungroup.svg
│ ├── odnoklassniki-square.svg
│ ├── odnoklassniki.svg
│ ├── opencart.svg
│ ├── openid.svg
│ ├── opera.svg
│ ├── optin-monster.svg
│ ├── outdent.svg
│ ├── pagelines.svg
│ ├── paint-brush.svg
│ ├── paper-plane-o.svg
│ ├── paper-plane.svg
│ ├── paperclip.svg
│ ├── paragraph.svg
│ ├── paste.svg
│ ├── pause-circle-o.svg
│ ├── pause-circle.svg
│ ├── pause.svg
│ ├── paw.svg
│ ├── paypal.svg
│ ├── pencil-square-o.svg
│ ├── pencil-square.svg
│ ├── pencil.svg
│ ├── percent.svg
│ ├── phone-square.svg
│ ├── phone.svg
│ ├── photo.svg
│ ├── picture-o.svg
│ ├── pie-chart.svg
│ ├── pied-piper-alt.svg
│ ├── pied-piper-pp.svg
│ ├── pied-piper.svg
│ ├── pinterest-p.svg
│ ├── pinterest-square.svg
│ ├── pinterest.svg
│ ├── plane.svg
│ ├── play-circle-o.svg
│ ├── play-circle.svg
│ ├── play.svg
│ ├── plug.svg
│ ├── plus-circle.svg
│ ├── plus-square-o.svg
│ ├── plus-square.svg
│ ├── plus.svg
│ ├── podcast.svg
│ ├── power-off.svg
│ ├── print.svg
│ ├── product-hunt.svg
│ ├── puzzle-piece.svg
│ ├── qq.svg
│ ├── qrcode.svg
│ ├── question-circle-o.svg
│ ├── question-circle.svg
│ ├── question.svg
│ ├── quora.svg
│ ├── quote-left.svg
│ ├── quote-right.svg
│ ├── ra.svg
│ ├── random.svg
│ ├── ravelry.svg
│ ├── rebel.svg
│ ├── recycle.svg
│ ├── reddit-alien.svg
│ ├── reddit-square.svg
│ ├── reddit.svg
│ ├── refresh.svg
│ ├── registered.svg
│ ├── remove.svg
│ ├── renren.svg
│ ├── reorder.svg
│ ├── repeat.svg
│ ├── reply-all.svg
│ ├── reply.svg
│ ├── resistance.svg
│ ├── retweet.svg
│ ├── rmb.svg
│ ├── road.svg
│ ├── rocket.svg
│ ├── rotate-left.svg
│ ├── rotate-right.svg
│ ├── rouble.svg
│ ├── rss-square.svg
│ ├── rss.svg
│ ├── rub.svg
│ ├── ruble.svg
│ ├── rupee.svg
│ ├── s15.svg
│ ├── safari.svg
│ ├── save.svg
│ ├── scissors.svg
│ ├── scribd.svg
│ ├── search-minus.svg
│ ├── search-plus.svg
│ ├── search.svg
│ ├── sellsy.svg
│ ├── send-o.svg
│ ├── send.svg
│ ├── server.svg
│ ├── share-alt-square.svg
│ ├── share-alt.svg
│ ├── share-square-o.svg
│ ├── share-square.svg
│ ├── share.svg
│ ├── shekel.svg
│ ├── sheqel.svg
│ ├── shield.svg
│ ├── ship.svg
│ ├── shirtsinbulk.svg
│ ├── shopping-bag.svg
│ ├── shopping-basket.svg
│ ├── shopping-cart.svg
│ ├── shower.svg
│ ├── sign-in.svg
│ ├── sign-language.svg
│ ├── sign-out.svg
│ ├── signal.svg
│ ├── signing.svg
│ ├── simplybuilt.svg
│ ├── sitemap.svg
│ ├── skyatlas.svg
│ ├── skype.svg
│ ├── slack.svg
│ ├── sliders.svg
│ ├── slideshare.svg
│ ├── smile-o.svg
│ ├── snapchat-ghost.svg
│ ├── snapchat-square.svg
│ ├── snapchat.svg
│ ├── snowflake-o.svg
│ ├── soccer-ball-o.svg
│ ├── sort-alpha-asc.svg
│ ├── sort-alpha-desc.svg
│ ├── sort-amount-asc.svg
│ ├── sort-amount-desc.svg
│ ├── sort-asc.svg
│ ├── sort-desc.svg
│ ├── sort-down.svg
│ ├── sort-numeric-asc.svg
│ ├── sort-numeric-desc.svg
│ ├── sort-up.svg
│ ├── sort.svg
│ ├── soundcloud.svg
│ ├── space-shuttle.svg
│ ├── spinner.svg
│ ├── spoon.svg
│ ├── spotify.svg
│ ├── square-o.svg
│ ├── square.svg
│ ├── stack-exchange.svg
│ ├── stack-overflow.svg
│ ├── star-half-empty.svg
│ ├── star-half-full.svg
│ ├── star-half-o.svg
│ ├── star-half.svg
│ ├── star-o.svg
│ ├── star.svg
│ ├── steam-square.svg
│ ├── steam.svg
│ ├── step-backward.svg
│ ├── step-forward.svg
│ ├── stethoscope.svg
│ ├── sticky-note-o.svg
│ ├── sticky-note.svg
│ ├── stop-circle-o.svg
│ ├── stop-circle.svg
│ ├── stop.svg
│ ├── street-view.svg
│ ├── strikethrough.svg
│ ├── stumbleupon-circle.svg
│ ├── stumbleupon.svg
│ ├── subscript.svg
│ ├── subway.svg
│ ├── suitcase.svg
│ ├── sun-o.svg
│ ├── superpowers.svg
│ ├── superscript.svg
│ ├── support.svg
│ ├── table.svg
│ ├── tablet.svg
│ ├── tachometer.svg
│ ├── tag.svg
│ ├── tags.svg
│ ├── tasks.svg
│ ├── taxi.svg
│ ├── telegram.svg
│ ├── television.svg
│ ├── tencent-weibo.svg
│ ├── terminal.svg
│ ├── text-height.svg
│ ├── text-width.svg
│ ├── th-large.svg
│ ├── th-list.svg
│ ├── th.svg
│ ├── themeisle.svg
│ ├── thermometer-0.svg
│ ├── thermometer-1.svg
│ ├── thermometer-2.svg
│ ├── thermometer-3.svg
│ ├── thermometer-4.svg
│ ├── thermometer-empty.svg
│ ├── thermometer-full.svg
│ ├── thermometer-half.svg
│ ├── thermometer-quarter.svg
│ ├── thermometer-three-quarters.svg
│ ├── thermometer.svg
│ ├── thumb-tack.svg
│ ├── thumbs-down.svg
│ ├── thumbs-o-down.svg
│ ├── thumbs-o-up.svg
│ ├── thumbs-up.svg
│ ├── ticket.svg
│ ├── times-circle-o.svg
│ ├── times-circle.svg
│ ├── times-rectangle-o.svg
│ ├── times-rectangle.svg
│ ├── times.svg
│ ├── tint.svg
│ ├── toggle-down.svg
│ ├── toggle-left.svg
│ ├── toggle-off.svg
│ ├── toggle-on.svg
│ ├── toggle-right.svg
│ ├── toggle-up.svg
│ ├── trademark.svg
│ ├── train.svg
│ ├── transgender-alt.svg
│ ├── transgender.svg
│ ├── trash-o.svg
│ ├── trash.svg
│ ├── tree.svg
│ ├── trello.svg
│ ├── tripadvisor.svg
│ ├── trophy.svg
│ ├── truck.svg
│ ├── try.svg
│ ├── tty.svg
│ ├── tumblr-square.svg
│ ├── tumblr.svg
│ ├── turkish-lira.svg
│ ├── tv.svg
│ ├── twitch.svg
│ ├── twitter-square.svg
│ ├── twitter.svg
│ ├── umbrella.svg
│ ├── underline.svg
│ ├── undo.svg
│ ├── universal-access.svg
│ ├── university.svg
│ ├── unlink.svg
│ ├── unlock-alt.svg
│ ├── unlock.svg
│ ├── unsorted.svg
│ ├── upload.svg
│ ├── usb.svg
│ ├── usd.svg
│ ├── user-circle-o.svg
│ ├── user-circle.svg
│ ├── user-md.svg
│ ├── user-o.svg
│ ├── user-plus.svg
│ ├── user-secret.svg
│ ├── user-times.svg
│ ├── user.svg
│ ├── users.svg
│ ├── vcard-o.svg
│ ├── vcard.svg
│ ├── venus-double.svg
│ ├── venus-mars.svg
│ ├── venus.svg
│ ├── viacoin.svg
│ ├── viadeo-square.svg
│ ├── viadeo.svg
│ ├── video-camera.svg
│ ├── vimeo-square.svg
│ ├── vimeo.svg
│ ├── vine.svg
│ ├── vk.svg
│ ├── volume-control-phone.svg
│ ├── volume-down.svg
│ ├── volume-off.svg
│ ├── volume-up.svg
│ ├── warning.svg
│ ├── wechat.svg
│ ├── weibo.svg
│ ├── weixin.svg
│ ├── whatsapp.svg
│ ├── wheelchair-alt.svg
│ ├── wheelchair.svg
│ ├── wifi.svg
│ ├── wikipedia-w.svg
│ ├── window-close-o.svg
│ ├── window-close.svg
│ ├── window-maximize.svg
│ ├── window-minimize.svg
│ ├── window-restore.svg
│ ├── windows.svg
│ ├── won.svg
│ ├── wordpress.svg
│ ├── wpbeginner.svg
│ ├── wpexplorer.svg
│ ├── wpforms.svg
│ ├── wrench.svg
│ ├── xing-square.svg
│ ├── xing.svg
│ ├── y-combinator-square.svg
│ ├── y-combinator.svg
│ ├── yahoo.svg
│ ├── yc-square.svg
│ ├── yc.svg
│ ├── yelp.svg
│ ├── yen.svg
│ ├── yoast.svg
│ ├── youtube-play.svg
│ ├── youtube-square.svg
│ └── youtube.svg
├── static
├── apple-icon.png
├── eng.traineddata.gz
├── favicon-alert.png
├── favicon.png
├── icon-144-maskable.png
├── icon-144.png
├── icon-150.png
├── icon-192-maskable.png
├── icon-192.png
├── icon-44.png
├── icon-48-maskable.png
├── icon-48.png
├── icon-50.png
├── icon-512-maskable.png
├── icon-512.png
├── icon-72-maskable.png
├── icon-72.png
├── icon-96-maskable.png
├── icon-96.png
├── icon-push-badge.png
├── icon-push-fa-retweet.png
├── icon-push-fa-star.png
├── icon-shortcut-fa-bell.png
├── icon-shortcut-fa-pencil.png
├── ipad_splash.png
├── ipadpro1_splash.png
├── ipadpro2_splash.png
├── ipadpro3_splash.png
├── iphone5_splash.png
├── iphone6_splash.png
├── iphoneplus_splash.png
├── iphonex_splash.png
├── iphonexr_splash.png
├── iphonexsmax_splash.png
├── screenshot-540-720-1.png
├── screenshot-540-720-2.png
└── screenshot-540-720-3.png
├── tests
├── blobUtils.js
├── fixtures.js
├── fixtures
│ ├── dump.sql
│ └── system.tgz
├── images.js
├── images
│ ├── kitten1.gif
│ ├── kitten1.jpg
│ ├── kitten1.mp4
│ ├── kitten2.gif
│ ├── kitten2.jpg
│ ├── kitten2.mp4
│ ├── kitten3.jpg
│ ├── kitten4.jpg
│ └── kitten5.jpg
├── indexedDBShims.js
├── loadMedia.cjs
├── roles.js
├── serverActions.js
├── spec
│ ├── 001-basic-spec.js
│ ├── 002-login-spec.js
│ ├── 003-basic-timeline-spec.js
│ ├── 004-pinned-statuses.js
│ ├── 005-status-types.js
│ ├── 006-tabindex.js
│ ├── 007-account-profile.js
│ ├── 008-status-media.js
│ ├── 009-threads.js
│ ├── 010-focus.js
│ ├── 011-reblog-favorites-count.js
│ ├── 012-compose.js
│ ├── 013-compose-media.js
│ ├── 014-compose-post-privacy.js
│ ├── 015-compose-content-warnings.js
│ ├── 016-external-links.js
│ ├── 017-compose-reply.js
│ ├── 018-compose-autosuggest.js
│ ├── 019-mention.js
│ ├── 020-themes.js
│ ├── 021-followers-follows.js
│ ├── 022-status-aria-label.js
│ ├── 023-mark-media-as-sensitive.js
│ ├── 024-shortcuts-navigation.js
│ ├── 025-shortcuts-status.js
│ ├── 026-shortcuts-notification.js
│ ├── 027-web-share-and-web-shortcuts.js
│ ├── 028-report-ui.js
│ ├── 029-back-button-modal.js
│ ├── 030-shortcuts-modal.js
│ ├── 031-account-filters.js
│ ├── 032-mute-dialog.js
│ ├── 033-notification-mentions.js
│ ├── 034-home-timeline-filters.js
│ ├── 035-notification-timeline-filters.js
│ ├── 036-disable-infinite-load.js
│ ├── 037-pin-timelines.js
│ ├── 038-memory-leaks.js
│ ├── 039-empty-list.js
│ ├── 040-shortcuts-search.js
│ ├── 041-wellness.js
│ ├── 042-headings.js
│ ├── 043-content-warnings.js
│ ├── 100-favorite-unfavorite.js
│ ├── 101-reblog-unreblog.js
│ ├── 102-notifications.js
│ ├── 103-compose.js
│ ├── 104-streaming.js
│ ├── 105-deletes.js
│ ├── 106-follow-requests.js
│ ├── 107-streaming-gap.js
│ ├── 108-compose-dialog.js
│ ├── 109-compose-media.js
│ ├── 110-compose-content-warnings.js
│ ├── 111-focus.js
│ ├── 112-status-links.js
│ ├── 113-block-unblock.js
│ ├── 114-mute-unmute.js
│ ├── 115-follow-unfollow.js
│ ├── 116-follow-requests.js
│ ├── 117-pin-unpin.js
│ ├── 118-display-name-custom-emoji.js
│ ├── 119-status-counts-update.js
│ ├── 120-status-aria-label.js
│ ├── 121-delete-and-redraft.js
│ ├── 122-replies-in-thread.js
│ ├── 123-notification-mentions.js
│ ├── 124-home-timeline-filters.js
│ ├── 125-notification-timeline-filters.js
│ ├── 126-polls.js
│ ├── 127-compose-polls.js
│ ├── 128-disable-infinite-load.js
│ ├── 129-wellness.js
│ ├── 130-focal-point.js
│ ├── 131-compose-autosuggest.js
│ ├── 132-threads-and-updates.js
│ ├── 133-favorites.js
│ ├── 134-community.js
│ ├── 135-bookmarks.js
│ ├── 136-empty-list.js
│ ├── 137-shortcuts-spoiler.js
│ ├── 138-word-filters.js
│ ├── 139-notify-denotify.js
│ └── 140-editing.js
├── spyDomListeners.js
├── submitMedia.js
├── unit
│ ├── test-database.mjs
│ ├── test-emoji.mjs
│ ├── test-id-sorting.mjs
│ ├── test-intl.mjs
│ ├── test-measure-text.mjs
│ ├── test-media-cache.mjs
│ ├── test-quick-lru.mjs
│ ├── test-shortcuts.mjs
│ ├── test-thread-ordering.mjs
│ ├── test-timeago.mjs
│ └── test-unescape.mjs
├── users.js
└── utils.js
├── vercel.json
├── webpack
├── client.config.js
├── rollup.config.js
├── server.config.js
├── service-worker.config.js
├── shared.config.js
├── svelte-intl-loader.js
├── terser.config.js
└── webpack.config.js
└── yarn.lock
/.dockerignore:
--------------------------------------------------------------------------------
1 | .git
2 | BREAKING_CHANGES.md
3 | CONTRIBUTING.md
4 | docs
5 | README.md
6 | tests
7 | .DS_Store
8 | /node_modules
9 | /__sapper__
10 | /mastodon
11 | /mastodon.log
12 | /src/template.html
13 | /static/*.css
14 | /static/icons.svg
15 | /static/inline-script.js.map
16 | /static/emoji-*.json
17 | /static/manifest.json
18 | /src/inline-script/checksum.js
19 | yarn-error.log
20 | /vercel.json
21 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | root = true
2 |
3 | [*]
4 | indent_style = space
5 | indent_size = 2
6 | end_of_line = lf
7 | charset = utf-8
8 | trim_trailing_whitespace = true
9 | insert_final_newline = true
10 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/accessibility.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: ♿ Report an accessibility issue
3 | about: Access issues are treated as high priority
4 | title: ''
5 | labels: '♿ accessibility'
6 | assignees: 'NickColley'
7 |
8 | ---
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/config.yml:
--------------------------------------------------------------------------------
1 | blank_issues_enabled: false
2 | contact_links:
3 | - name: 💡 Suggest a new feature or idea
4 | url: https://github.com/NickColley/semaphore/discussions/categories/new-features-and-ideas
5 | about: Missing something in Semaphore? Accessibility related features and ideas will be prioritised.
6 | - name: ❔ Ask a question
7 | url: https://fosstodon.org/@semaphore
8 | about: Send us a toot on Mastodon
9 |
10 |
11 |
--------------------------------------------------------------------------------
/.github/workflows/unit-tests.yml:
--------------------------------------------------------------------------------
1 | name: Unit tests
2 | on:
3 | pull_request:
4 | branches: [ main ]
5 | jobs:
6 | test:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v3
10 | - uses: actions/setup-node@v3
11 | with:
12 | node-version: '14'
13 | cache: 'yarn'
14 | - run: yarn --frozen-lockfile
15 | - run: yarn lint
16 | - run: yarn test-vercel-json
17 | - run: yarn test-unit
18 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /node_modules
3 | /__sapper__
4 | /mastodon
5 | /mastodon.log
6 | /src/template.html
7 | /static/*.css
8 | /static/icons.svg
9 | /static/inline-script.js.map
10 | /static/emoji-*.json
11 | /static/manifest.json
12 | /static/TwemojiCountryFlags.woff2
13 | /src/inline-script/checksum.js
14 | yarn-error.log
15 |
16 | .now
17 | .vercel
18 | /webpack/*.cjs
19 |
--------------------------------------------------------------------------------
/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname $0)/_/husky.sh"
3 |
4 | set -e
5 | set -x
6 |
7 | PATH="$PATH:./node_modules/.bin"
8 |
9 | lint-staged
10 | run-s build-vercel-json
11 | git add vercel.json
12 |
--------------------------------------------------------------------------------
/.testcaferc.json:
--------------------------------------------------------------------------------
1 | {
2 | "hostname": "localhost",
3 | "quarantineMode": true,
4 | "screenshots": {
5 | "takeOnFails": false
6 | },
7 | "skipJsErrors": true,
8 | "stopOnFirstFail": true
9 | }
10 |
--------------------------------------------------------------------------------
/.vercelignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | /node_modules
3 | /__sapper__
4 | /mastodon
5 | /mastodon.log
6 | /src/template.html
7 | /static/*.css
8 | /static/icons.svg
9 | /static/inline-script.js.map
10 | /static/emoji-*.json
11 | /static/manifest.json
12 | /src/inline-script/checksum.js
13 | yarn-error.log
14 |
--------------------------------------------------------------------------------
/BREAKING_CHANGES.md:
--------------------------------------------------------------------------------
1 | # Breaking changes
2 |
3 | There are no breaking changes yet.
4 |
5 | > See [previous breaking changes in Pinafore](https://github.com/nolanlawson/pinafore/releases).
6 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # Changelog
2 |
3 | For full release notes, see [GitHub releases](https://github.com/NickColley/semaphore/releases).
4 |
5 | For breaking changes, see [BREAKING_CHANGES.md](https://github.com/NickColley/semaphore/blob/main/BREAKING_CHANGES.md).
6 |
--------------------------------------------------------------------------------
/bin/backup-mastodon-data.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | set -x
4 | set -e
5 |
6 | PGPASSWORD=semaphore pg_dump -U semaphore -w semaphore_development -h 127.0.0.1 > tests/fixtures/dump.sql
7 | cd mastodon/public/system
8 | tar -czf ../../../tests/fixtures/system.tgz .
9 |
--------------------------------------------------------------------------------
/bin/browser-shim.js:
--------------------------------------------------------------------------------
1 | // browser shims that run in node, so that page-lifecycle won't error
2 | global.self = global
3 | global.document = {
4 | visibilityState: 'visible',
5 | hasFocus: () => true,
6 | wasDiscarded: false
7 | }
8 | global.addEventListener = () => {}
9 | global.removeEventListener = () => {}
10 |
--------------------------------------------------------------------------------
/bin/copy-vercel-json.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # Designed to be run before yarn build, and then tested with test-vercel-json-unchanged.sh
4 |
5 | cp ./vercel.json /tmp/vercel-old.json
6 |
--------------------------------------------------------------------------------
/bin/terserOptions.js:
--------------------------------------------------------------------------------
1 | export default {
2 | ecma: 8,
3 | mangle: true,
4 | compress: {
5 | pure_funcs: [
6 | 'console.log' // remove console logs in production
7 | ]
8 | },
9 | output: {
10 | comments: false
11 | },
12 | safari10: true
13 | }
14 |
--------------------------------------------------------------------------------
/bin/test-vercel-json-unchanged.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | # In CI, we need to make sure the vercel.json file is built correctly,
4 | # or else it will mess up the deployment to Vercel
5 |
6 | if ! diff -q /tmp/vercel-old.json ./vercel.json &>/dev/null; then
7 | diff /tmp/vercel-old.json ./vercel.json
8 | echo "vercel.json changed, run yarn build and make sure everything looks okay"
9 | exit 1
10 | fi
11 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | ---
2 | version: "3"
3 | services:
4 | semaphore:
5 | restart: unless-stopped
6 | build:
7 | context: .
8 | dockerfile: Dockerfile
9 | image: semaphore:latest
10 | ports:
11 | - 4002:4002
12 |
--------------------------------------------------------------------------------
/docs/Screenshot1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/docs/Screenshot1.png
--------------------------------------------------------------------------------
/docs/Screenshot2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/docs/Screenshot2.png
--------------------------------------------------------------------------------
/docs/Screenshot3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/docs/Screenshot3.png
--------------------------------------------------------------------------------
/docs/Screenshot4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/docs/Screenshot4.png
--------------------------------------------------------------------------------
/docs/Screenshot5.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/docs/Screenshot5.png
--------------------------------------------------------------------------------
/docs/Screenshot6.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/docs/Screenshot6.png
--------------------------------------------------------------------------------
/src/routes/_a11y/getAccountAccessibleName.js:
--------------------------------------------------------------------------------
1 | import { removeEmoji } from '../_utils/removeEmoji.js'
2 |
3 | export function getAccountAccessibleName (account, omitEmojiInDisplayNames) {
4 | const emojis = account.emojis
5 | let displayName = account.display_name || account.username
6 | if (omitEmojiInDisplayNames) {
7 | displayName = removeEmoji(displayName, emojis) || displayName
8 | }
9 | return displayName
10 | }
11 |
--------------------------------------------------------------------------------
/src/routes/_actions/composePoll.js:
--------------------------------------------------------------------------------
1 | import { store } from '../_store/store.js'
2 |
3 | export function enablePoll (realm) {
4 | store.setComposeData(realm, {
5 | poll: {
6 | options: [
7 | '',
8 | ''
9 | ]
10 | }
11 | })
12 | }
13 |
14 | export function disablePoll (realm) {
15 | store.setComposeData(realm, {
16 | poll: null
17 | })
18 | }
19 |
--------------------------------------------------------------------------------
/src/routes/_actions/getRecentStatusesForAccount.js:
--------------------------------------------------------------------------------
1 | import { store } from '../_store/store.js'
2 | import { getTimeline } from '../_api/timelines.js'
3 |
4 | export async function getRecentStatusesForAccount (accountId) {
5 | const { currentInstance, accessToken } = store.get()
6 | return (await getTimeline(currentInstance, accessToken, `account/${accountId}`, null, null, 20)).items
7 | }
8 |
--------------------------------------------------------------------------------
/src/routes/_actions/mention.js:
--------------------------------------------------------------------------------
1 | import { importShowComposeDialog } from '../_components/dialog/asyncDialogs/importShowComposeDialog.js'
2 | import { store } from '../_store/store.js'
3 |
4 | export async function composeNewStatusMentioning (account) {
5 | store.setComposeData('dialog', { text: `@${account.acct} ` })
6 | const showComposeDialog = await importShowComposeDialog()
7 | showComposeDialog()
8 | }
9 |
--------------------------------------------------------------------------------
/src/routes/_actions/postPrivacy.js:
--------------------------------------------------------------------------------
1 |
2 | import { store } from '../_store/store.js'
3 |
4 | export function setPostPrivacy (realm, postPrivacyKey) {
5 | store.setComposeData(realm, { postPrivacy: postPrivacyKey })
6 | }
7 |
--------------------------------------------------------------------------------
/src/routes/_actions/report.js:
--------------------------------------------------------------------------------
1 | import { importShowReportDialog } from '../_components/dialog/asyncDialogs/importShowReportDialog.js'
2 |
3 | export async function reportStatusOrAccount ({ status, account }) {
4 | const showReportDialog = await importShowReportDialog()
5 | showReportDialog({ status, account })
6 | }
7 |
--------------------------------------------------------------------------------
/src/routes/_actions/toggleMute.js:
--------------------------------------------------------------------------------
1 | import { importShowMuteDialog } from '../_components/dialog/asyncDialogs/importShowMuteDialog.js'
2 | import { setAccountMuted } from './mute.js'
3 |
4 | export async function toggleMute (account, mute) {
5 | if (mute) {
6 | (await importShowMuteDialog())(account)
7 | } else {
8 | await setAccountMuted(account.id, mute, /* notifications */ false, /* toastOnSuccess */ true)
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/src/routes/_actions/updateStatus.js:
--------------------------------------------------------------------------------
1 | import { database } from '../_database/database.js'
2 | import { scheduleIdleTask } from '../_utils/scheduleIdleTask.js'
3 |
4 | async function doUpdateStatus (instanceName, newStatus) {
5 | console.log('updating status', newStatus)
6 | await database.updateStatus(instanceName, newStatus)
7 | }
8 |
9 | export function updateStatus (instanceName, newStatus) {
10 | scheduleIdleTask(() => {
11 | /* no await */ doUpdateStatus(instanceName, newStatus)
12 | })
13 | }
14 |
--------------------------------------------------------------------------------
/src/routes/_api/delete.js:
--------------------------------------------------------------------------------
1 | import { auth, basename } from './utils.js'
2 | import { del, WRITE_TIMEOUT } from '../_utils/ajax.js'
3 |
4 | export async function deleteStatus (instanceName, accessToken, statusId) {
5 | const url = `${basename(instanceName)}/api/v1/statuses/${statusId}`
6 | return del(url, auth(accessToken), { timeout: WRITE_TIMEOUT })
7 | }
8 |
--------------------------------------------------------------------------------
/src/routes/_api/emoji.js:
--------------------------------------------------------------------------------
1 | import { auth, basename } from './utils.js'
2 | import { DEFAULT_TIMEOUT, get } from '../_utils/ajax.js'
3 |
4 | export function getCustomEmoji (instanceName, accessToken) {
5 | const url = `${basename(instanceName)}/api/v1/custom_emojis`
6 | return get(url, auth(accessToken), { timeout: DEFAULT_TIMEOUT })
7 | }
8 |
--------------------------------------------------------------------------------
/src/routes/_api/instance.js:
--------------------------------------------------------------------------------
1 | import { get, DEFAULT_TIMEOUT } from '../_utils/ajax.js'
2 | import { auth, basename } from './utils.js'
3 |
4 | export function getInstanceInfo (instanceName, accessToken) {
5 | const url = `${basename(instanceName)}/api/v1/instance`
6 | // accessToken is required in limited federation mode, but elsewhere we don't need it (e.g. during login)
7 | const headers = accessToken ? auth(accessToken) : null
8 | return get(url, headers, { timeout: DEFAULT_TIMEOUT })
9 | }
10 |
--------------------------------------------------------------------------------
/src/routes/_api/pinnedStatuses.js:
--------------------------------------------------------------------------------
1 | import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax.js'
2 | import { auth, basename } from './utils.js'
3 |
4 | export async function getPinnedStatuses (instanceName, accessToken, accountId) {
5 | let url = `${basename(instanceName)}/api/v1/accounts/${accountId}/statuses`
6 | url += '?' + paramsString({
7 | limit: 40,
8 | pinned: true
9 | })
10 | return get(url, auth(accessToken), { timeout: DEFAULT_TIMEOUT })
11 | }
12 |
--------------------------------------------------------------------------------
/src/routes/_api/relationships.js:
--------------------------------------------------------------------------------
1 | import { basename, auth } from './utils.js'
2 | import { get, paramsString, DEFAULT_TIMEOUT } from '../_utils/ajax.js'
3 |
4 | export async function getRelationship (instanceName, accessToken, accountId) {
5 | const url = `${basename(instanceName)}/api/v1/accounts/relationships?${paramsString({ id: accountId })}`
6 | const res = await get(url, auth(accessToken), { timeout: DEFAULT_TIMEOUT })
7 | return res[0]
8 | }
9 |
--------------------------------------------------------------------------------
/src/routes/_api/report.js:
--------------------------------------------------------------------------------
1 | import { auth, basename } from './utils.js'
2 | import { post } from '../_utils/ajax.js'
3 |
4 | export async function report (instanceName, accessToken, accountId, statusIds, comment, forward) {
5 | const url = `${basename(instanceName)}/api/v1/reports`
6 | return post(url, {
7 | account_id: accountId,
8 | status_ids: statusIds,
9 | comment,
10 | forward
11 | }, auth(accessToken))
12 | }
13 |
--------------------------------------------------------------------------------
/src/routes/_api/showReblogs.js:
--------------------------------------------------------------------------------
1 | import { auth, basename } from './utils.js'
2 | import { post, WRITE_TIMEOUT } from '../_utils/ajax.js'
3 |
4 | export function setShowReblogs (instanceName, accessToken, accountId, showReblogs) {
5 | const url = `${basename(instanceName)}/api/v1/accounts/${accountId}/follow`
6 | return post(url, { reblogs: !!showReblogs }, auth(accessToken), { timeout: WRITE_TIMEOUT })
7 | }
8 |
--------------------------------------------------------------------------------
/src/routes/_api/updateCredentials.js:
--------------------------------------------------------------------------------
1 | import { WRITE_TIMEOUT, patch } from '../_utils/ajax.js'
2 | import { auth, basename } from './utils.js'
3 |
4 | export async function updateCredentials (instanceName, accessToken, accountData) {
5 | const url = `${basename(instanceName)}/api/v1/accounts/update_credentials`
6 | return patch(url, accountData, auth(accessToken), { timeout: WRITE_TIMEOUT })
7 | }
8 |
--------------------------------------------------------------------------------
/src/routes/_api/utils.js:
--------------------------------------------------------------------------------
1 | function targetIsLocalhost (instanceName) {
2 | return instanceName.startsWith('localhost:') || instanceName.startsWith('127.0.0.1:')
3 | }
4 |
5 | export function basename (instanceName) {
6 | if (targetIsLocalhost(instanceName)) {
7 | return `http://${instanceName}`
8 | }
9 | return `https://${instanceName}`
10 | }
11 |
12 | export function auth (accessToken) {
13 | return {
14 | Authorization: `Bearer ${accessToken}`
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/src/routes/_components/DynamicHeading.html:
--------------------------------------------------------------------------------
1 | {#if level === 2}
2 |
3 | {:else}
4 |
5 | {/if}
6 |
--------------------------------------------------------------------------------
/src/routes/_components/HiddenFromSSR.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
10 |
--------------------------------------------------------------------------------
/src/routes/_components/InformationalFooter.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
15 |
--------------------------------------------------------------------------------
/src/routes/_components/compose/ComposeLengthGauge.html:
--------------------------------------------------------------------------------
1 |
6 |
17 |
--------------------------------------------------------------------------------
/src/routes/_components/compose/ComposeLengthIndicator.html:
--------------------------------------------------------------------------------
1 |
7 |
18 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowAccountProfileOptionsDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowAccountProfileOptionsDialog = () => import(
2 | '../creators/showAccountProfileOptionsDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowComposeDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowComposeDialog = () => import(
2 | '../creators/showComposeDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowCopyDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowCopyDialog = () => import(
2 | '../creators/showCopyDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowEmojiDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowEmojiDialog = () => import(
2 | '../creators/showEmojiDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowMediaDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowMediaDialog = () => import(
2 | '../creators/showMediaDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowMediaEditDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowMediaEditDialog = () => import(
2 | '../creators/showMediaEditDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowMuteDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowMuteDialog = () => import(
2 | '../creators/showMuteDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowPostPrivacyDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowPostPrivacyDialog = () => import(
2 | '../creators/showPostPrivacyDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowReportDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowReportDialog = () => import(
2 | '../creators/showReportDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowShortcutHelpDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowShortcutHelpDialog = () => import(
2 | '../creators/showShortcutHelpDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowStatusOptionsDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowStatusOptionsDialog = () => import(
2 | '../creators/showStatusOptionsDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowTextConfirmationDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowTextConfirmationDialog = () => import(
2 | '../creators/showTextConfirmationDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/asyncDialogs/importShowWordFilterDialog.js:
--------------------------------------------------------------------------------
1 | export const importShowWordFilterDialog = () => import(
2 | '../creators/showWordFilterDialog.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showAccountProfileOptionsDialog.js:
--------------------------------------------------------------------------------
1 | import AccountProfileOptionsDialog from '../components/AccountProfileOptionsDialog.html'
2 | import { showDialog } from './showDialog.js'
3 |
4 | export default function showAccountProfileOptionsDialog (account, relationship, verifyCredentials) {
5 | return showDialog(AccountProfileOptionsDialog, {
6 | label: 'intl.profileOptions',
7 | title: '',
8 | account,
9 | relationship,
10 | verifyCredentials
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showComposeDialog.js:
--------------------------------------------------------------------------------
1 | import ComposeDialog from '../components/ComposeDialog.html'
2 | import { showDialog } from './showDialog.js'
3 |
4 | export default function showComposeDialog () {
5 | return showDialog(ComposeDialog, { label: 'intl.composeStatus' })
6 | }
7 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showCopyDialog.js:
--------------------------------------------------------------------------------
1 | import CopyDialog from '../components/CopyDialog.html'
2 | import { showDialog } from './showDialog.js'
3 |
4 | export default function showCopyDialog (text) {
5 | return showDialog(CopyDialog, {
6 | label: 'intl.copyLink',
7 | title: 'intl.copyLink',
8 | text
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showDialog.js:
--------------------------------------------------------------------------------
1 | import { createDialogElement } from '../helpers/createDialogElement.js'
2 | import { createDialogId } from '../helpers/createDialogId.js'
3 |
4 | export function showDialog (Dialog, data) {
5 | const dialog = new Dialog({
6 | target: createDialogElement(),
7 | data: Object.assign({
8 | id: createDialogId()
9 | }, data)
10 | })
11 | dialog.show()
12 | return dialog
13 | }
14 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showEmojiDialog.js:
--------------------------------------------------------------------------------
1 | import EmojiDialog from '../components/EmojiDialog.html'
2 | import { showDialog } from './showDialog.js'
3 |
4 | export default function showEmojiDialog (realm) {
5 | return showDialog(EmojiDialog, {
6 | label: 'intl.emoji',
7 | title: 'intl.emoji',
8 | realm
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showMediaDialog.js:
--------------------------------------------------------------------------------
1 | import MediaDialog from '../components/MediaDialog.html'
2 | import { showDialog } from './showDialog.js'
3 |
4 | export default function showMediaDialog (mediaItems, scrolledItem) {
5 | return showDialog(MediaDialog, {
6 | label: 'intl.media',
7 | mediaItems,
8 | scrolledItem
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showMediaEditDialog.js:
--------------------------------------------------------------------------------
1 | import MediaFocalPointDialog from '../components/MediaEditDialog.html'
2 | import { showDialog } from './showDialog.js'
3 |
4 | export default function showMediaEditDialog (realm, index, type) {
5 | return showDialog(MediaFocalPointDialog, {
6 | label: 'intl.editMedia',
7 | title: 'intl.editMedia',
8 | realm,
9 | index,
10 | type
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showMuteDialog.js:
--------------------------------------------------------------------------------
1 | import MuteDialog from '../components/MuteDialog.html'
2 | import { showDialog } from './showDialog.js'
3 |
4 | export default function showMuteDialog (account) {
5 | return showDialog(MuteDialog, {
6 | label: 'intl.mute',
7 | account
8 | })
9 | }
10 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showPostPrivacyDialog.js:
--------------------------------------------------------------------------------
1 | import PostPrivacyDialog from '../components/PostPrivacyDialog.html'
2 | import { showDialog } from './showDialog.js'
3 |
4 | export default function showPostPrivacyDialog (realm) {
5 | return showDialog(PostPrivacyDialog, {
6 | label: 'intl.postPrivacy',
7 | title: 'intl.postPrivacy',
8 | realm
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showReportDialog.js:
--------------------------------------------------------------------------------
1 | import ReportDialog from '../components/ReportDialog.html'
2 | import { showDialog } from './showDialog.js'
3 | import { formatIntl } from '../../../_utils/formatIntl.js'
4 |
5 | export default function showReportDialog ({ account, status }) {
6 | const label = formatIntl('intl.reportAccount', { account: `@${account.acct}` })
7 | return showDialog(ReportDialog, {
8 | label,
9 | title: label,
10 | account,
11 | status
12 | })
13 | }
14 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showShortcutHelpDialog.js:
--------------------------------------------------------------------------------
1 | import ShortcutHelpDialog from '../components/ShortcutHelpDialog.html'
2 | import { showDialog } from './showDialog.js'
3 |
4 | export default function showShortcutHelpDialog (options) {
5 | return showDialog(ShortcutHelpDialog, Object.assign({
6 | label: 'intl.shortcutHelp'
7 | }, options))
8 | }
9 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showStatusOptionsDialog.js:
--------------------------------------------------------------------------------
1 | import StatusOptionsDialog from '../components/StatusOptionsDialog.html'
2 | import { showDialog } from './showDialog.js'
3 |
4 | export default function showStatusOptionsDialog (status) {
5 | return showDialog(StatusOptionsDialog, {
6 | label: 'intl.statusOptions',
7 | title: '',
8 | status
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showTextConfirmationDialog.js:
--------------------------------------------------------------------------------
1 | import TextConfirmationDialog from '../components/TextConfirmationDialog.html'
2 | import { showDialog } from './showDialog.js'
3 |
4 | export default function showTextConfirmationDialog (options) {
5 | return showDialog(TextConfirmationDialog, Object.assign({
6 | label: 'intl.confirm'
7 | }, options))
8 | }
9 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/creators/showWordFilterDialog.js:
--------------------------------------------------------------------------------
1 | import WordFilterDialog from '../components/WordFilterDialog.html'
2 | import { showDialog } from './showDialog.js'
3 |
4 | export default function showReportDialog ({ filter, instanceName }) {
5 | const label = filter ? 'intl.editFilter' : 'intl.addFilter'
6 | return showDialog(WordFilterDialog, {
7 | label,
8 | title: label,
9 | filter,
10 | instanceName
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/helpers/closeDialog.js:
--------------------------------------------------------------------------------
1 | import { emit } from '../../../_utils/eventBus.js'
2 |
3 | export function close () {
4 | const { id } = this.get()
5 | emit('closeDialog', id)
6 | }
7 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/helpers/createDialogElement.js:
--------------------------------------------------------------------------------
1 | export function createDialogElement () {
2 | const div = document.createElement('div')
3 | div.setAttribute('class', 'modal-dialog')
4 | div.setAttribute('aria-hidden', 'true')
5 | document.body.appendChild(div)
6 | return div
7 | }
8 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/helpers/createDialogId.js:
--------------------------------------------------------------------------------
1 | let count = -1
2 |
3 | export function createDialogId () {
4 | return ++count
5 | }
6 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/helpers/onCreateDialog.js:
--------------------------------------------------------------------------------
1 | import { on } from '../../../_utils/eventBus.js'
2 |
3 | function onDestroy (thisId) {
4 | const { id } = this.get()
5 | if (id !== thisId) {
6 | return
7 | }
8 | this.destroy()
9 | }
10 |
11 | export function oncreate () {
12 | on('destroyDialog', this, onDestroy)
13 | }
14 |
--------------------------------------------------------------------------------
/src/routes/_components/dialog/helpers/showDialog.js:
--------------------------------------------------------------------------------
1 | import { emit } from '../../../_utils/eventBus.js'
2 |
3 | export function show () {
4 | const { id } = this.get()
5 | emit('showDialog', id)
6 | }
7 |
--------------------------------------------------------------------------------
/src/routes/_components/search/HashtagSearchResult.html:
--------------------------------------------------------------------------------
1 |
2 | {'#' + hashtag.name}
3 |
4 |
6 |
14 |
--------------------------------------------------------------------------------
/src/routes/_components/search/StatusSearchResult.html:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
8 |
--------------------------------------------------------------------------------
/src/routes/_components/settings/UISettingsStyles.html:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/src/routes/_components/settings/instance/GenericInstanceSettingsStyle.html:
--------------------------------------------------------------------------------
1 |
11 |
--------------------------------------------------------------------------------
/src/routes/_components/timeline/MoreHeaderVirtualWrapper.html:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/routes/_database/clear.js:
--------------------------------------------------------------------------------
1 | import { accountsCache, clearCache, metaCache, statusesCache } from './cache.js'
2 | import { deleteDatabase } from './databaseLifecycle.js'
3 |
4 | export async function clearDatabaseForInstance (instanceName) {
5 | clearCache(statusesCache, instanceName)
6 | clearCache(accountsCache, instanceName)
7 | clearCache(metaCache, instanceName)
8 | await deleteDatabase(instanceName)
9 | }
10 |
--------------------------------------------------------------------------------
/src/routes/_database/database.js:
--------------------------------------------------------------------------------
1 | import { asyncDatabase } from './asyncDatabase.js'
2 | export { asyncDatabase as database }
3 |
--------------------------------------------------------------------------------
/src/routes/_database/timelines/cacheStatus.js:
--------------------------------------------------------------------------------
1 | import {
2 | accountsCache, setInCache, statusesCache
3 | } from '../cache.js'
4 |
5 | export function cacheStatus (status, instanceName) {
6 | setInCache(statusesCache, instanceName, status.id, status)
7 | setInCache(accountsCache, instanceName, status.account.id, status.account)
8 | if (status.reblog) {
9 | setInCache(accountsCache, instanceName, status.reblog.account.id, status.reblog.account)
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/routes/_database/timelines/fetchAccount.js:
--------------------------------------------------------------------------------
1 | export function fetchAccount (accountsStore, id, callback) {
2 | accountsStore.get(id).onsuccess = e => {
3 | callback(e.target.result)
4 | }
5 | }
6 |
--------------------------------------------------------------------------------
/src/routes/_database/utils.js:
--------------------------------------------------------------------------------
1 | export function deleteAll (store, index, keyRange) {
2 | index.getAllKeys(keyRange).onsuccess = e => {
3 | for (const result of e.target.result) {
4 | store.delete(result)
5 | }
6 | }
7 | }
8 |
--------------------------------------------------------------------------------
/src/routes/_pages/accounts/[accountId]/index.html:
--------------------------------------------------------------------------------
1 |
2 |
11 |
--------------------------------------------------------------------------------
/src/routes/_pages/accounts/[accountId]/media.html:
--------------------------------------------------------------------------------
1 |
2 |
11 |
--------------------------------------------------------------------------------
/src/routes/_pages/accounts/[accountId]/with_replies.html:
--------------------------------------------------------------------------------
1 |
2 |
11 |
--------------------------------------------------------------------------------
/src/routes/_static/autosuggest.js:
--------------------------------------------------------------------------------
1 | export const SEARCH_RESULTS_LIMIT = 4
2 |
--------------------------------------------------------------------------------
/src/routes/_static/blocks.js:
--------------------------------------------------------------------------------
1 | export const DOMAIN_BLOCKS = [
2 | 'gab.com',
3 | 'gab.ai'
4 | ]
5 |
--------------------------------------------------------------------------------
/src/routes/_static/blurhash.js:
--------------------------------------------------------------------------------
1 | export const BLURHASH_RESOLUTION = 32
2 |
--------------------------------------------------------------------------------
/src/routes/_static/database.js:
--------------------------------------------------------------------------------
1 | export const CLEANUP_TIME_AGO = 5 * 24 * 60 * 60 * 1000 // five days ago
2 | export const CLEANUP_DELAY = 5 * 60 * 1000 // five minutes
3 |
--------------------------------------------------------------------------------
/src/routes/_static/fonts.js:
--------------------------------------------------------------------------------
1 | // same as the one used for SemaphoreEmoji
2 | export const FONT_FAMILY = '"Twemoji Mozilla","Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol",' +
3 | '"Noto Color Emoji","EmojiOne Color","Android Emoji",sans-serif'
4 |
--------------------------------------------------------------------------------
/src/routes/_static/instanceSettings.js:
--------------------------------------------------------------------------------
1 | export const HOME_REBLOGS = 'homeReblogs'
2 | export const HOME_REPLIES = 'homeReplies'
3 |
4 | export const NOTIFICATION_REBLOGS = 'notificationReblogs'
5 | export const NOTIFICATION_FAVORITES = 'notificationFavs'
6 | export const NOTIFICATION_FOLLOWS = 'notificationFollows'
7 | export const NOTIFICATION_MENTIONS = 'notificationMentions'
8 | export const NOTIFICATION_POLLS = 'notificationPolls'
9 | export const NOTIFICATION_SUBSCRIPTIONS = 'notificationSubscriptions'
10 |
--------------------------------------------------------------------------------
/src/routes/_static/intl.js:
--------------------------------------------------------------------------------
1 | export const DEFAULT_LOCALE = 'en-US'
2 | export const LOCALE = process.env.LOCALE || DEFAULT_LOCALE
3 |
--------------------------------------------------------------------------------
/src/routes/_static/pages.js:
--------------------------------------------------------------------------------
1 | export const PAGE_HISTORY_SIZE = 10
2 |
--------------------------------------------------------------------------------
/src/routes/_static/share.js:
--------------------------------------------------------------------------------
1 | export const WEB_SHARE_TARGET_DATA_IDB_KEY = 'web-share-data'
2 |
--------------------------------------------------------------------------------
/src/routes/_static/timelines.js:
--------------------------------------------------------------------------------
1 | export const TIMELINE_BATCH_SIZE = 20
2 |
3 | export const timelines = {
4 | home: { name: 'home', label: 'intl.home' },
5 | local: { name: 'local', label: 'intl.local' },
6 | federated: { name: 'federated', label: 'intl.federated' }
7 | }
8 |
--------------------------------------------------------------------------------
/src/routes/_store/computations/computations.js:
--------------------------------------------------------------------------------
1 | import { instanceComputations } from './instanceComputations.js'
2 | import { navComputations } from './navComputations.js'
3 |
4 | export function computations (store) {
5 | instanceComputations(store)
6 | navComputations(store)
7 | }
8 |
--------------------------------------------------------------------------------
/src/routes/_store/loggedInStoreExtensions.js:
--------------------------------------------------------------------------------
1 | import { loggedInComputations } from './computations/loggedInComputations.js'
2 | import { loggedInObservers } from './observers/loggedInObservers.js'
3 | import { loggedInMixins } from './mixins/loggedInMixins.js'
4 |
5 | console.log('imported logged in observers and computations')
6 | loggedInMixins()
7 | loggedInComputations()
8 | loggedInObservers()
9 |
--------------------------------------------------------------------------------
/src/routes/_store/mixins/loggedInMixins.js:
--------------------------------------------------------------------------------
1 | import { timelineMixins } from './timelineMixins.js'
2 | import { statusMixins } from './statusMixins.js'
3 | import { autosuggestMixins } from './autosuggestMixins.js'
4 | import { composeMixins } from './composeMixins.js'
5 | import { SemaphoreStore as Store } from '../store.js'
6 |
7 | export function loggedInMixins () {
8 | composeMixins(Store)
9 | timelineMixins(Store)
10 | statusMixins(Store)
11 | autosuggestMixins(Store)
12 | }
13 |
--------------------------------------------------------------------------------
/src/routes/_store/mixins/mixins.js:
--------------------------------------------------------------------------------
1 | import { instanceMixins } from './instanceMixins.js'
2 |
3 | export function mixins (Store) {
4 | instanceMixins(Store)
5 | }
6 |
--------------------------------------------------------------------------------
/src/routes/_store/observers/bottomNavObservers.js:
--------------------------------------------------------------------------------
1 | const style = process.browser && document.getElementById('theBottomNavStyle')
2 |
3 | export function bottomNavObservers (store) {
4 | if (!process.browser) {
5 | return
6 | }
7 |
8 | store.observe('bottomNav', bottomNav => {
9 | // disables or enables the style
10 | style.setAttribute('media', bottomNav ? 'all' : 'only x') // disable or enable the style
11 | }, { init: false }) // init: false because the inline script takes care of it
12 | }
13 |
--------------------------------------------------------------------------------
/src/routes/_store/observers/logOutObservers.js:
--------------------------------------------------------------------------------
1 | import { onUserIsLoggedOut } from '../../_actions/onUserIsLoggedOut.js'
2 |
3 | export function logOutObservers (store) {
4 | if (!process.browser) {
5 | return
6 | }
7 | store.observe('isUserLoggedIn', isUserLoggedIn => {
8 | if (!isUserLoggedIn) {
9 | onUserIsLoggedOut()
10 | }
11 | })
12 | }
13 |
--------------------------------------------------------------------------------
/src/routes/_store/observers/pageVisibilityObservers.js:
--------------------------------------------------------------------------------
1 | export function pageVisibilityObservers (store) {
2 | if (!process.browser) {
3 | return
4 | }
5 |
6 | document.addEventListener('visibilitychange', () => {
7 | store.set({ pageVisibilityHidden: document.hidden })
8 | })
9 | }
10 |
--------------------------------------------------------------------------------
/src/routes/_store/observers/touchObservers.js:
--------------------------------------------------------------------------------
1 | export function touchObservers (store) {
2 | if (!process.browser) {
3 | return
4 | }
5 |
6 | const onTouch = () => {
7 | store.set({ isUserTouching: true })
8 | window.removeEventListener('touchstart', onTouch)
9 | }
10 |
11 | window.addEventListener('touchstart', onTouch, { passive: true })
12 | }
13 |
--------------------------------------------------------------------------------
/src/routes/_thirdparty/lodash/objects.src.js:
--------------------------------------------------------------------------------
1 | export { isEqual, difference, uniqBy } from 'lodash-es'
2 |
--------------------------------------------------------------------------------
/src/routes/_thirdparty/lodash/timers.src.js:
--------------------------------------------------------------------------------
1 | export { debounce, throttle } from 'lodash-es'
2 |
--------------------------------------------------------------------------------
/src/routes/_utils/announceAriaLivePolite.js:
--------------------------------------------------------------------------------
1 | const ariaLiveElement = process.browser && document.getElementById('theAriaLive')
2 |
3 | export function announceAriaLivePolite (text) {
4 | ariaLiveElement.textContent = text
5 | }
6 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importArrowKeyNavigation.js:
--------------------------------------------------------------------------------
1 | export const importArrowKeyNavigation = () => import(
2 | 'arrow-key-navigation'
3 | )
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importComposeBox.js:
--------------------------------------------------------------------------------
1 | export const importComposeBox = () => import(
2 | '../../_components/compose/ComposeBox.html'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importDatabase.js:
--------------------------------------------------------------------------------
1 | export const importDatabase = () => import(
2 | '../../_database/databaseApis.js'
3 | )
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importEmojiMart.js:
--------------------------------------------------------------------------------
1 | export const importEmojiMart = () => import(
2 | '../../_react/createEmojiMartPickerFromData.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importList.js:
--------------------------------------------------------------------------------
1 | export const importList = () => import(
2 | '../../_components/list/List.html'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importLoggedInStoreExtensions.js:
--------------------------------------------------------------------------------
1 | export const importLoggedInStoreExtensions = () => import(
2 | '../../_store/loggedInStoreExtensions.js'
3 | )
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importNavShortcuts.js:
--------------------------------------------------------------------------------
1 | export const importNavShortcuts = () => import(
2 | '../../_components/NavShortcuts.html'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importNotificationVirtualListItem.js:
--------------------------------------------------------------------------------
1 | export const importNotificationVirtualListItem = () => import(
2 | '../../_components/timeline/NotificationVirtualListItem.html'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importPageLifecycle.js:
--------------------------------------------------------------------------------
1 | export const importPageLifecycle = () => import(
2 | 'page-lifecycle/dist/lifecycle.mjs'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importSnackbar.js:
--------------------------------------------------------------------------------
1 | export const importSnackbar = () => import(
2 | '../../_components/snackbar/Snackbar.html'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importStatusVirtualListItem.js:
--------------------------------------------------------------------------------
1 | export const importStatusVirtualListItem = () => import(
2 | '../../_components/timeline/StatusVirtualListItem.html'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importTesseractWorker.js:
--------------------------------------------------------------------------------
1 | export const importTesseractWorker = () => import(
2 | '../../_utils/tesseractWorker.js'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importTimeline.js:
--------------------------------------------------------------------------------
1 | export const importTimeline = () => import(
2 | '../../_components/timeline/Timeline.html'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importToast.js:
--------------------------------------------------------------------------------
1 | export const importToast = () => import(
2 | '../../_components/toast/Toast.html'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importVirtualList.js:
--------------------------------------------------------------------------------
1 | export const importVirtualList = () => import(
2 | '../../_components/virtualList/VirtualList.html'
3 | ).then(mod => mod.default)
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/asyncModules/importVirtualListStore.js:
--------------------------------------------------------------------------------
1 | export const importVirtualListStore = () => import(
2 | '../../_components/virtualList/virtualListStore.js'
3 | )
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/classname.js:
--------------------------------------------------------------------------------
1 | export function classname () {
2 | let res = ''
3 | const len = arguments.length
4 | let i = -1
5 | while (++i < len) {
6 | const item = arguments[i]
7 | if (item) {
8 | if (res) {
9 | res += ' '
10 | }
11 | res += item
12 | }
13 | }
14 | return res
15 | }
16 |
--------------------------------------------------------------------------------
/src/routes/_utils/convertCustomEmojiToEmojiPickerFormat.js:
--------------------------------------------------------------------------------
1 | export function convertCustomEmojiToEmojiPickerFormat (customEmoji, autoplayGifs) {
2 | if (!customEmoji) {
3 | return []
4 | }
5 | return customEmoji.filter(emoji => emoji.visible_in_picker).map(emoji => ({
6 | name: emoji.shortcode,
7 | shortcodes: [emoji.shortcode],
8 | url: autoplayGifs ? emoji.url : emoji.static_url,
9 | category: emoji.category
10 | }))
11 | }
12 |
--------------------------------------------------------------------------------
/src/routes/_utils/coordsToPercent.js:
--------------------------------------------------------------------------------
1 | export const coordsToPercent = coord => ((1 + coord) / 2) * 100
2 |
3 | export const percentToCoords = percent => ((percent / 100) * 2) - 1
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/createStatusOrNotificationUuid.js:
--------------------------------------------------------------------------------
1 | export function createStatusOrNotificationUuid (currentInstance, timelineType, timelineValue, notificationId, statusId) {
2 | return `${currentInstance}/${timelineType}/${timelineValue}/${notificationId || ''}/${statusId || ''}`
3 | }
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/decodeImage.js:
--------------------------------------------------------------------------------
1 | export function decodeImage (img) {
2 | if (typeof img.decode === 'function' && !img.src.startsWith('data:image/png;base64,')) {
3 | return img.decode()
4 | }
5 |
6 | return new Promise((resolve, reject) => {
7 | img.onload = resolve
8 | img.onerror = reject
9 | })
10 | }
11 |
--------------------------------------------------------------------------------
/src/routes/_utils/doubleRAF.js:
--------------------------------------------------------------------------------
1 | export function doubleRAF (fn) {
2 | requestAnimationFrame(() => requestAnimationFrame(fn))
3 | }
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/emojiRegex.js:
--------------------------------------------------------------------------------
1 | import emojiRegex from 'emoji-regex'
2 | import { thunk } from './thunk.js'
3 |
4 | export const getEmojiRegex = thunk(emojiRegex)
5 |
--------------------------------------------------------------------------------
/src/routes/_utils/getIdFromItemSummaries.js:
--------------------------------------------------------------------------------
1 | export function getFirstIdFromItemSummaries (itemSummaries) {
2 | return itemSummaries &&
3 | itemSummaries[0] &&
4 | itemSummaries[0].id
5 | }
6 |
7 | export function getLastIdFromItemSummaries (itemSummaries) {
8 | return itemSummaries &&
9 | itemSummaries[itemSummaries.length - 1] &&
10 | itemSummaries[itemSummaries.length - 1].id
11 | }
12 |
--------------------------------------------------------------------------------
/src/routes/_utils/getImageNativeDimensions.js:
--------------------------------------------------------------------------------
1 | import { decodeImage } from './decodeImage.js'
2 |
3 | export async function getImageNativeDimensions (url) {
4 | const img = document.createElement('img')
5 | img.src = url
6 | await decodeImage(img)
7 | return {
8 | width: img.naturalWidth,
9 | height: img.naturalHeight
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/src/routes/_utils/handleRegex.js:
--------------------------------------------------------------------------------
1 | /* eslint-disable */
2 | import { thunk } from './thunk.js'
3 |
4 | export const handleRegex = thunk(() => /(^|[^\/\w])@(([a-z0-9_]+)@[a-z0-9\.\-]+[a-z0-9]+)/ig)
5 | /* eslint-enable */
6 |
--------------------------------------------------------------------------------
/src/routes/_utils/isDarkTheme.js:
--------------------------------------------------------------------------------
1 | import { themes } from '../_static/themes.js'
2 | import { DEFAULT_THEME } from './themeEngine.js'
3 |
4 | export function isDarkTheme (themeName) {
5 | const theme = themes.find(_ => _.name === themeName) || themes.find(_ => _.name === DEFAULT_THEME)
6 | return theme.dark
7 | }
8 |
--------------------------------------------------------------------------------
/src/routes/_utils/loadCSS.js:
--------------------------------------------------------------------------------
1 | export function loadCSS (href) {
2 | const existingLink = document.querySelector(`link[href="${href}"]`)
3 |
4 | if (existingLink) {
5 | return
6 | }
7 | const link = document.createElement('link')
8 | link.rel = 'stylesheet'
9 | link.href = href
10 |
11 | document.head.appendChild(link)
12 | }
13 |
--------------------------------------------------------------------------------
/src/routes/_utils/loadingMask.js:
--------------------------------------------------------------------------------
1 | import LoadingMask from '../_components/LoadingMask.html'
2 |
3 | let loadingMask
4 |
5 | if (process.browser) {
6 | loadingMask = new LoadingMask({
7 | target: document.querySelector('#loading-mask')
8 | })
9 | if (process.env.NODE_ENV !== 'production') {
10 | window.loadingMask = loadingMask // for debugging
11 | }
12 | } else {
13 | loadingMask = {
14 | }
15 | }
16 |
17 | export { loadingMask }
18 |
--------------------------------------------------------------------------------
/src/routes/_utils/massageStatusPlainText.js:
--------------------------------------------------------------------------------
1 | // Glitch Social can have statuses that just contain blockquote/ol/ul, no p
2 | const STARTING_TAG_REGEX = /^<(?:p|blockquote|ol|ul)>/i
3 |
4 | export function massageStatusPlainText (text) {
5 | // GNU Social and Pleroma don't add tags, so wrap them
6 | if (text && !STARTING_TAG_REGEX.test(text)) {
7 | text = `
${text}
`
8 | }
9 | return text
10 | }
11 |
--------------------------------------------------------------------------------
/src/routes/_utils/massageUserText.js:
--------------------------------------------------------------------------------
1 | import { emojifyText } from './emojifyText.js'
2 | import { massageStatusPlainText } from './massageStatusPlainText.js'
3 |
4 | export function massageUserText (text, emojis, $autoplayGifs) {
5 | text = text || ''
6 | text = emojifyText(text, emojis, $autoplayGifs)
7 | text = massageStatusPlainText(text)
8 | return text
9 | }
10 |
--------------------------------------------------------------------------------
/src/routes/_utils/normalizePageName.js:
--------------------------------------------------------------------------------
1 | // return the page name for purposes of figuring out which part of the nav
2 | // is highlighted/selected
3 | export function normalizePageName (page) {
4 | // notifications/mentions and settings/foo are a special case; they show as selected in the nav
5 | return page === 'notifications/mentions'
6 | ? 'notifications'
7 | : (page && page.startsWith('settings/'))
8 | ? 'settings'
9 | : page
10 | }
11 |
--------------------------------------------------------------------------------
/src/routes/_utils/once.js:
--------------------------------------------------------------------------------
1 | // svelte helper to add a .once() method similar to .on, but only fires once
2 |
3 | export function once (eventName, callback) {
4 | const listener = this.on(eventName, eventValue => {
5 | listener.cancel()
6 | callback(eventValue)
7 | })
8 | }
9 |
--------------------------------------------------------------------------------
/src/routes/_utils/polyfills/loadNonCriticalPolyfills.js:
--------------------------------------------------------------------------------
1 | import { importFocusVisible } from './asyncPolyfills.js'
2 | import { supportsFocusVisible } from '../supportsFocusVisible.js'
3 |
4 | export function loadNonCriticalPolyfills () {
5 | return Promise.all([
6 | !supportsFocusVisible() && importFocusVisible()
7 | ])
8 | }
9 |
--------------------------------------------------------------------------------
/src/routes/_utils/queueMicrotask.js:
--------------------------------------------------------------------------------
1 | // via https://developer.mozilla.org/en-US/docs/Web/API/WindowOrWorkerGlobalScope/queueMicrotask
2 | function queueMicrotaskPolyfill (callback) {
3 | Promise.resolve()
4 | .then(callback)
5 | .catch(e => setTimeout(() => { throw e }))
6 | }
7 |
8 | const qM = typeof queueMicrotask === 'function' ? queueMicrotask : queueMicrotaskPolyfill
9 |
10 | export {
11 | qM as queueMicrotask
12 | }
13 |
--------------------------------------------------------------------------------
/src/routes/_utils/removeEmoji.js:
--------------------------------------------------------------------------------
1 | import { replaceAll } from './strings.js'
2 | import { replaceEmoji } from './replaceEmoji.js'
3 |
4 | export function removeEmoji (text, emojis) {
5 | // remove custom emoji
6 | if (emojis) {
7 | for (const emoji of emojis) {
8 | const shortcodeWithColons = `:${emoji.shortcode}:`
9 | text = replaceAll(text, shortcodeWithColons, '')
10 | }
11 | }
12 | // remove native emoji
13 | return replaceEmoji(text, () => '').trim()
14 | }
15 |
--------------------------------------------------------------------------------
/src/routes/_utils/safeLocalStorage.js:
--------------------------------------------------------------------------------
1 | import localStorageMemory from 'localstorage-memory'
2 | import { testHasLocalStorage } from './testStorage.js'
3 |
4 | const safeLocalStorage = testHasLocalStorage() ? localStorage : localStorageMemory
5 |
6 | export { safeLocalStorage }
7 |
--------------------------------------------------------------------------------
/src/routes/_utils/safeParse.js:
--------------------------------------------------------------------------------
1 | export function safeParse (str) {
2 | return !str ? undefined : (str === 'undefined' ? undefined : JSON.parse(str))
3 | }
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/scrollToTop.js:
--------------------------------------------------------------------------------
1 | import { getScrollContainer } from './scrollContainer.js'
2 | import { smoothScroll } from './smoothScroll.js'
3 |
4 | export function scrollToTop (smooth) {
5 | const scroller = getScrollContainer()
6 | const { scrollTop } = scroller
7 | if (scrollTop === 0) {
8 | return false
9 | }
10 | if (smooth) {
11 | smoothScroll(scroller, 0, /* horizontal */ false, /* preferFast */ true)
12 | } else {
13 | scroller.scrollTop = 0
14 | }
15 | return true
16 | }
17 |
--------------------------------------------------------------------------------
/src/routes/_utils/strings.js:
--------------------------------------------------------------------------------
1 | export function replaceAll (string, replacee, replacement) {
2 | if (!string.length || !replacee.length) {
3 | return string
4 | }
5 | let idx
6 | let pos = 0
7 | while (true) {
8 | idx = string.indexOf(replacee, pos)
9 | if (idx === -1) {
10 | break
11 | }
12 | string = string.substring(0, idx) + replacement + string.substring(idx + replacee.length)
13 | pos = idx + replacement.length
14 | }
15 | return string
16 | }
17 |
--------------------------------------------------------------------------------
/src/routes/_utils/supportsFocusVisible.js:
--------------------------------------------------------------------------------
1 | import { thunk } from './thunk.js'
2 | import { supportsSelector } from './supportsSelector.js'
3 | import { isFirefoxPre90 } from './userAgent/isFirefoxPre90.js'
4 |
5 | // Disabling in Firefox <90 due to bugs:
6 | // https://bugzilla.mozilla.org/show_bug.cgi?id=1699154
7 | // https://bugzilla.mozilla.org/show_bug.cgi?id=1711057
8 | export const supportsFocusVisible = thunk(() => (!isFirefoxPre90() && supportsSelector(':focus-visible')))
9 |
--------------------------------------------------------------------------------
/src/routes/_utils/supportsSelector.js:
--------------------------------------------------------------------------------
1 | // See https://stackoverflow.com/a/8533927
2 | export function supportsSelector (selector) {
3 | const style = document.createElement('style')
4 | document.head.appendChild(style)
5 | try {
6 | style.sheet.insertRule(selector + '{}', 0)
7 | } catch (e) {
8 | return false
9 | } finally {
10 | document.head.removeChild(style)
11 | }
12 | return true
13 | }
14 |
--------------------------------------------------------------------------------
/src/routes/_utils/thunk.js:
--------------------------------------------------------------------------------
1 | // Run a function once, then cache the result and return the cached result thereafter
2 | export function thunk (func) {
3 | let cached
4 | let runOnce
5 | return () => {
6 | if (!runOnce) {
7 | cached = func()
8 | runOnce = true
9 | }
10 | return cached
11 | }
12 | }
13 |
--------------------------------------------------------------------------------
/src/routes/_utils/urlIsCrossOrigin.js:
--------------------------------------------------------------------------------
1 | export function urlIsCrossOrigin (href) {
2 | try {
3 | return new URL(href, location.href).origin !== location.origin
4 | } catch (e) {
5 | console.error('Ignoring malformed URL', href)
6 | return true
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/routes/_utils/urlRegex.js:
--------------------------------------------------------------------------------
1 | import { thunk } from './thunk.js'
2 |
3 | export const urlRegex = thunk(() => {
4 | // this is provided at build time to avoid having a lot of runtime code just to build
5 | // a static regex
6 | return process.env.URL_REGEX
7 | })
8 |
--------------------------------------------------------------------------------
/src/routes/_utils/userAgent/isChrome.js:
--------------------------------------------------------------------------------
1 | import { thunk } from '../thunk.js'
2 |
3 | export const isChrome = thunk(() => process.browser && /Chrome/.test(navigator.userAgent))
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/userAgent/isChromePre87.js:
--------------------------------------------------------------------------------
1 | import { isChrome } from './isChrome.js'
2 | import { thunk } from '../thunk.js'
3 |
4 | // https://caniuse.com/cookie-store-api
5 | export const isChromePre87 = thunk(() => (process.browser && isChrome() && typeof cookieStore === 'undefined'))
6 |
--------------------------------------------------------------------------------
/src/routes/_utils/userAgent/isFirefoxPre90.js:
--------------------------------------------------------------------------------
1 | import { thunk } from '../thunk.js'
2 |
3 | export const isFirefoxPre90 = thunk(() => {
4 | return process.browser &&
5 | // https://stackoverflow.com/a/9851769/680742
6 | typeof InstallTrigger !== 'undefined' &&
7 | // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/at#browser_compatibility
8 | !Array.prototype.at
9 | })
10 |
--------------------------------------------------------------------------------
/src/routes/_utils/userAgent/isIOS.js:
--------------------------------------------------------------------------------
1 | import { thunk } from '../thunk.js'
2 |
3 | export const isIOS = thunk(() => process.browser && /iP(?:hone|ad|od)/.test(navigator.userAgent))
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/userAgent/isIOSPre12Point2.js:
--------------------------------------------------------------------------------
1 | // IntersectionObserver introduced in iOS 12.2 https://caniuse.com/#feat=intersectionobserver
2 | import { thunk } from '../thunk.js'
3 | import { isIOS } from './isIOS.js'
4 |
5 | export const isIOSPre12Point2 = thunk(() => process.browser && isIOS() &&
6 | !(typeof IntersectionObserver === 'function' &&
7 | IntersectionObserver.toString().includes('[native code]')))
8 |
--------------------------------------------------------------------------------
/src/routes/_utils/userAgent/isIOSPre13.js:
--------------------------------------------------------------------------------
1 | // PointerEvent introduced in iOS 13 https://caniuse.com/#feat=pointer
2 | import { thunk } from '../thunk.js'
3 | import { isIOS } from '../userAgent/isIOS.js'
4 |
5 | export const isIOSPre13 = thunk(() => process.browser && isIOS() &&
6 | !(typeof PointerEvent === 'function' &&
7 | PointerEvent.toString().includes('[native code]')))
8 |
--------------------------------------------------------------------------------
/src/routes/_utils/userAgent/isKaiOS.js:
--------------------------------------------------------------------------------
1 | import { thunk } from '../thunk.js'
2 |
3 | export const isKaiOS = thunk(() => process.browser && /KAIOS/.test(navigator.userAgent))
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/userAgent/isMac.js:
--------------------------------------------------------------------------------
1 | import { thunk } from '../thunk.js'
2 |
3 | export const isMac = thunk(() => process.browser && /mac/i.test(navigator.platform))
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/userAgent/isMobile.js:
--------------------------------------------------------------------------------
1 | import { thunk } from '../thunk.js'
2 |
3 | export const isMobile = thunk(() => process.browser && navigator.userAgent.match(/(?:iPhone|iPod|iPad|Android|KAIOS)/))
4 |
--------------------------------------------------------------------------------
/src/routes/_utils/userAgent/isWebKit.js:
--------------------------------------------------------------------------------
1 | import { thunk } from '../thunk.js'
2 |
3 | export const isWebKit = thunk(() => process.browser && typeof webkitIndexedDB !== 'undefined')
4 |
--------------------------------------------------------------------------------
/src/routes/blocked.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/bookmarks.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/community/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/direct.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/favorites.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/federated.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/lists/[listId].html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/local.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/muted.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/notifications/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/notifications/mentions.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/pinned.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/requests.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/search.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/settings/about.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/settings/hotkeys.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/settings/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/routes/tags/[tagName].html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
21 |
--------------------------------------------------------------------------------
/src/scss/themes/_dark_navbar.scss:
--------------------------------------------------------------------------------
1 | :root {
2 | --nav-bg: #{lighten($body-bg-color, 10%)};
3 | --nav-a-bg-hover: #{lighten($body-bg-color, 25%)};
4 | --nav-active-bg: #{lighten($body-bg-color, 35%)};
5 | --nav-a-selected-bg: #{lighten($body-bg-color, 25%)};
6 | --nav-a-selected-bg-hover: #{lighten($body-bg-color, 40%)};
7 | --nav-a-selected-active-bg: #{lighten($body-bg-color, 50%)};
8 |
9 | --button-primary-bg: #{darken($main-theme-color, 5%)};
10 | }
11 |
--------------------------------------------------------------------------------
/src/scss/themes/_dark_scrollbars.scss:
--------------------------------------------------------------------------------
1 | $scrollbar-face: #{lighten($main-theme-color, 5%)} !default;
2 | $scrollbar-face-hover: #{lighten($main-theme-color, 7%)} !default;
3 | $scrollbar-face-active: #{lighten($main-theme-color, 3%)} !default;
4 | $scrollbar-track: #{lighten($body-bg-color, 7%)} !default;
5 |
6 | @import "_scrollbars.scss";
--------------------------------------------------------------------------------
/src/scss/themes/_default.scss:
--------------------------------------------------------------------------------
1 | $main-theme-color: #6248CA;
2 | $body-bg-color: lighten($main-theme-color, 38%);
3 | $anchor-color: $main-theme-color;
4 | $main-text-color: #333;
5 | $border-color: #dadada;
6 | $main-bg-color: white;
7 | $secondary-text-color: white;
8 | $toast-border: #fafafa;
9 | $toast-bg: #333;
10 | $focus-outline: lighten($main-theme-color, 30%);
11 | $compose-background: lighten($main-theme-color, 32%);
12 |
13 | @import "_base.scss";
14 | @import "_light_scrollbars.scss";
--------------------------------------------------------------------------------
/src/scss/themes/_light_scrollbars.scss:
--------------------------------------------------------------------------------
1 | $scrollbar-face: #{lighten($main-theme-color, 18%)} !default;
2 | $scrollbar-face-hover: #{lighten($main-theme-color, 20%)} !default;
3 | $scrollbar-face-active: #{lighten($main-theme-color, 15%)} !default;
4 | $scrollbar-track: #{darken($body-bg-color, 3%)} !default;
5 |
6 | @import "_scrollbars.scss";
--------------------------------------------------------------------------------
/src/scss/themes/_scrollbars.scss:
--------------------------------------------------------------------------------
1 | :root {
2 | --scrollbar-face-color: #{$scrollbar-face};
3 | --scrollbar-track-color: #{$scrollbar-track};
4 | --scrollbar-border-radius: 0;
5 | --scrollbar-face-color-hover: #{$scrollbar-face-hover};
6 | --scrollbar-face-color-active: #{$scrollbar-face-active};
7 | --scrollbar-width: calc(20px + .25em);
8 | --scrollbar-height: calc(20px + .25em);
9 | --scrollbar-background-color: transparent;
10 | }
11 |
--------------------------------------------------------------------------------
/src/scss/themes/oaken.scss:
--------------------------------------------------------------------------------
1 | $main-theme-color: saddlebrown;
2 | $body-bg-color: lighten($main-theme-color, 60%);
3 | $anchor-color: $main-theme-color;
4 | $main-text-color: #333;
5 | $border-color: #dadada;
6 | $main-bg-color: white;
7 | $secondary-text-color: white;
8 | $toast-border: #fafafa;
9 | $toast-bg: #333;
10 | $focus-outline: lighten($main-theme-color, 30%);
11 | $compose-background: lighten($main-theme-color, 32%);
12 |
13 | @import "_base.scss";
14 | @import "_light_scrollbars.scss";
15 |
--------------------------------------------------------------------------------
/src/scss/themes/scarlet.scss:
--------------------------------------------------------------------------------
1 | $main-theme-color: #e04e41;
2 | $body-bg-color: lighten($main-theme-color, 38%);
3 | $anchor-color: $main-theme-color;
4 | $main-text-color: #333;
5 | $border-color: #dadada;
6 | $main-bg-color: white;
7 | $secondary-text-color: white;
8 | $toast-border: #fafafa;
9 | $toast-bg: #333;
10 | $focus-outline: lighten($main-theme-color, 30%);
11 | $compose-background: lighten($main-theme-color, 32%);
12 |
13 | @import "_base.scss";
14 | @import "_light_scrollbars.scss";
15 |
--------------------------------------------------------------------------------
/src/scss/themes/seafoam.scss:
--------------------------------------------------------------------------------
1 | $main-theme-color: #177380;
2 | $body-bg-color: lighten($main-theme-color, 60%);
3 | $anchor-color: $main-theme-color;
4 | $main-text-color: #333;
5 | $border-color: #dadada;
6 | $main-bg-color: white;
7 | $secondary-text-color: white;
8 | $toast-border: #fafafa;
9 | $toast-bg: #333;
10 | $focus-outline: lighten($main-theme-color, 50%);
11 | $compose-background: lighten($main-theme-color, 52%);
12 |
13 | @import "_base.scss";
14 | @import "_light_scrollbars.scss";
--------------------------------------------------------------------------------
/src/static/icon-shortcut-fa-bell.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/src/static/icon-shortcut-fa-bell.xcf
--------------------------------------------------------------------------------
/src/static/icon-shortcut-fa-pencil.xcf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/src/static/icon-shortcut-fa-pencil.xcf
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/README.md:
--------------------------------------------------------------------------------
1 | Copied from https://raw.githubusercontent.com/encharm/Font-Awesome-SVG-PNG
2 |
3 | Version used: 1.2.2
4 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/adjust.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/adn.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/angle-double-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/angle-double-right.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/angle-down.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/angle-left.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/angle-right.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/angle-up.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/archive.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/area-chart.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/arrow-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/arrow-left.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/arrow-right.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/arrow-up.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/arrows-h.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/arrows-v.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/backward.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/ban.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/bandcamp.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/bank.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/bar-chart-o.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/bar-chart.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/bars.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/battery-0.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/battery-1.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/battery-2.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/battery-3.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/battery-4.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/battery-empty.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/battery-full.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/battery-half.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/battery-quarter.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/battery.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/bed.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/beer.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/bell.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/black-tie.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/bluetooth-b.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/bolt.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/bookmark-o.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/bookmark.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/briefcase.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/buysellads.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/camera.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/caret-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/caret-left.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/caret-right.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/caret-up.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/check-circle.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/check-square.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/check.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/chevron-circle-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/chevron-circle-left.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/chevron-circle-right.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/chevron-circle-up.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/chevron-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/chevron-left.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/chevron-right.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/chevron-up.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/child.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/circle-o-notch.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/circle-o.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/circle-thin.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/circle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/clock-o.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/close.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/cloud.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/coffee.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/columns.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/comment.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/compass.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/credit-card-alt.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/css3.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/cube.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/dashcube.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/delicious.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/deviantart.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/diamond.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/digg.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/dropbox.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/eject.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/ellipsis-h.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/ellipsis-v.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/envelope.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/eraser.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/exclamation-triangle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/exclamation.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/fa.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/facebook-f.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/facebook-official.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/facebook-square.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/facebook.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/fast-backward.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/fast-forward.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/file-o.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/file.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/filter.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/flag.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/flash.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/flask.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/flickr.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/folder-o.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/folder.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/font-awesome.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/forward.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/genderless.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/gg.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/gitlab.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/gittip.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/glass.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/google.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/gratipay.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/hacker-news.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/heart.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/hotel.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/houzz.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/html5.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/i-cursor.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/inbox.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/industry.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/info-circle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/info.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/institution.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/level-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/level-up.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/line-chart.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/location-arrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/lock.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/long-arrow-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/long-arrow-left.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/long-arrow-right.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/long-arrow-up.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/magic.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/map-marker.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/map-o.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/map-pin.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/maxcdn.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/medium.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/minus-circle.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/minus-square.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/minus.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/modx.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/mouse-pointer.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/navicon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/openid.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/paper-plane-o.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/paper-plane.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/paragraph.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/pause.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/pencil.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/pie-chart.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/play-circle.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/play.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/plug.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/plus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/product-hunt.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/remove.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/renren.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/reorder.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/reply-all.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/reply.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/search-minus.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/search.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/send-o.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/send.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/shield.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/sort-asc.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/sort-desc.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/sort-down.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/sort-up.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/sort.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/spoon.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/square-o.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/square.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/stack-exchange.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/stack-overflow.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/star-half-empty.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/star-half-full.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/star-half-o.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/star-half.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/star-o.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/star.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/step-backward.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/step-forward.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/sticky-note-o.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/sticky-note.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/stop-circle.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/stop.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/suitcase.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/tablet.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/tag.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/telegram.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/terminal.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/thumb-tack.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/times.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/train.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/trello.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/tumblr.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/twitch.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/university.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/unlock-alt.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/unlock.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/unsorted.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/user.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/viacoin.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/video-camera.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/vimeo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/volume-off.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/window-maximize.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/window-minimize.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/window-restore.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/windows.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/xing.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/y-combinator-square.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/y-combinator.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/yahoo.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/yc-square.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/src/thirdparty/font-awesome-svg-png/white/svg/yc.svg:
--------------------------------------------------------------------------------
1 |
2 |
--------------------------------------------------------------------------------
/static/apple-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/apple-icon.png
--------------------------------------------------------------------------------
/static/eng.traineddata.gz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/eng.traineddata.gz
--------------------------------------------------------------------------------
/static/favicon-alert.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/favicon-alert.png
--------------------------------------------------------------------------------
/static/favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/favicon.png
--------------------------------------------------------------------------------
/static/icon-144-maskable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-144-maskable.png
--------------------------------------------------------------------------------
/static/icon-144.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-144.png
--------------------------------------------------------------------------------
/static/icon-150.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-150.png
--------------------------------------------------------------------------------
/static/icon-192-maskable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-192-maskable.png
--------------------------------------------------------------------------------
/static/icon-192.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-192.png
--------------------------------------------------------------------------------
/static/icon-44.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-44.png
--------------------------------------------------------------------------------
/static/icon-48-maskable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-48-maskable.png
--------------------------------------------------------------------------------
/static/icon-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-48.png
--------------------------------------------------------------------------------
/static/icon-50.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-50.png
--------------------------------------------------------------------------------
/static/icon-512-maskable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-512-maskable.png
--------------------------------------------------------------------------------
/static/icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-512.png
--------------------------------------------------------------------------------
/static/icon-72-maskable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-72-maskable.png
--------------------------------------------------------------------------------
/static/icon-72.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-72.png
--------------------------------------------------------------------------------
/static/icon-96-maskable.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-96-maskable.png
--------------------------------------------------------------------------------
/static/icon-96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-96.png
--------------------------------------------------------------------------------
/static/icon-push-badge.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-push-badge.png
--------------------------------------------------------------------------------
/static/icon-push-fa-retweet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-push-fa-retweet.png
--------------------------------------------------------------------------------
/static/icon-push-fa-star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-push-fa-star.png
--------------------------------------------------------------------------------
/static/icon-shortcut-fa-bell.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-shortcut-fa-bell.png
--------------------------------------------------------------------------------
/static/icon-shortcut-fa-pencil.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/icon-shortcut-fa-pencil.png
--------------------------------------------------------------------------------
/static/ipad_splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/ipad_splash.png
--------------------------------------------------------------------------------
/static/ipadpro1_splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/ipadpro1_splash.png
--------------------------------------------------------------------------------
/static/ipadpro2_splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/ipadpro2_splash.png
--------------------------------------------------------------------------------
/static/ipadpro3_splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/ipadpro3_splash.png
--------------------------------------------------------------------------------
/static/iphone5_splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/iphone5_splash.png
--------------------------------------------------------------------------------
/static/iphone6_splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/iphone6_splash.png
--------------------------------------------------------------------------------
/static/iphoneplus_splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/iphoneplus_splash.png
--------------------------------------------------------------------------------
/static/iphonex_splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/iphonex_splash.png
--------------------------------------------------------------------------------
/static/iphonexr_splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/iphonexr_splash.png
--------------------------------------------------------------------------------
/static/iphonexsmax_splash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/iphonexsmax_splash.png
--------------------------------------------------------------------------------
/static/screenshot-540-720-1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/screenshot-540-720-1.png
--------------------------------------------------------------------------------
/static/screenshot-540-720-2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/screenshot-540-720-2.png
--------------------------------------------------------------------------------
/static/screenshot-540-720-3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/static/screenshot-540-720-3.png
--------------------------------------------------------------------------------
/tests/blobUtils.js:
--------------------------------------------------------------------------------
1 | export function base64StringToBlob (base64, type) {
2 | function binaryStringToArrayBuffer (binary) {
3 | const length = binary.length
4 | const buf = new ArrayBuffer(length)
5 | const arr = new Uint8Array(buf)
6 | let i = -1
7 | while (++i < length) {
8 | arr[i] = binary.charCodeAt(i)
9 | }
10 | return buf
11 | }
12 |
13 | const parts = [binaryStringToArrayBuffer(atob(base64))]
14 | return type ? new Blob(parts, { type }) : new Blob(parts)
15 | }
16 |
--------------------------------------------------------------------------------
/tests/fixtures/system.tgz:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/tests/fixtures/system.tgz
--------------------------------------------------------------------------------
/tests/images/kitten1.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/tests/images/kitten1.gif
--------------------------------------------------------------------------------
/tests/images/kitten1.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/tests/images/kitten1.jpg
--------------------------------------------------------------------------------
/tests/images/kitten1.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/tests/images/kitten1.mp4
--------------------------------------------------------------------------------
/tests/images/kitten2.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/tests/images/kitten2.gif
--------------------------------------------------------------------------------
/tests/images/kitten2.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/tests/images/kitten2.jpg
--------------------------------------------------------------------------------
/tests/images/kitten2.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/tests/images/kitten2.mp4
--------------------------------------------------------------------------------
/tests/images/kitten3.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/tests/images/kitten3.jpg
--------------------------------------------------------------------------------
/tests/images/kitten4.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/tests/images/kitten4.jpg
--------------------------------------------------------------------------------
/tests/images/kitten5.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/NickColley/semaphore/a7eaec339186330d402c67cebdd1fce110dc0155/tests/images/kitten5.jpg
--------------------------------------------------------------------------------
/tests/indexedDBShims.js:
--------------------------------------------------------------------------------
1 | import { indexedDB, IDBKeyRange } from 'fake-indexeddb'
2 |
3 | global.indexedDB = indexedDB
4 | global.IDBKeyRange = IDBKeyRange
5 |
--------------------------------------------------------------------------------
/tests/loadMedia.cjs:
--------------------------------------------------------------------------------
1 | const fs = require('fs')
2 | const path = require('path')
3 |
4 | // Have to use CJS so this file can run in TestCafe. Otherwise it's impossible to get __dirname to work in both envs
5 | const dirname = __dirname
6 |
7 | exports.loadMedia = function loadMedia (filename) {
8 | const filepath = path.join(dirname, 'images', filename)
9 | if (!fs.existsSync(filepath)) {
10 | throw new Error('File does not exist: ' + filepath)
11 | }
12 | return fs.createReadStream(filepath)
13 | }
14 |
--------------------------------------------------------------------------------
/webpack/terser.config.js:
--------------------------------------------------------------------------------
1 | import TerserWebpackPlugin from 'terser-webpack-plugin'
2 | import terserOptions from '../bin/terserOptions'
3 |
4 | export default () => new TerserWebpackPlugin({
5 | exclude: /(tesseract-asset|page-lifecycle)/, // tesseract causes problems, page-lifecycle is pre-minified
6 | parallel: true,
7 | terserOptions
8 | })
9 |
--------------------------------------------------------------------------------
/webpack/webpack.config.js:
--------------------------------------------------------------------------------
1 | import client from './client.config.js'
2 | import server from './server.config.js'
3 | import serviceworker from './service-worker.config.js'
4 |
5 | export default {
6 | client,
7 | server,
8 | serviceworker
9 | }
10 |
--------------------------------------------------------------------------------