├── .eslintignore
├── .eslintrc.js
├── .gitattributes
├── .github
├── ISSUE_TEMPLATE
│ ├── bug_report.md
│ └── feature_request.md
└── workflows
│ └── main.yml
├── .gitignore
├── .husky
├── .gitignore
└── pre-commit
├── .npm-upgrade.json
├── .nvmrc
├── .prettierignore
├── .prettierrc.json
├── .vscode
├── extensions.json
├── i18n-ally-custom-framework.yml
└── settings.json
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── artifacts
└── .gitkeep
├── config
└── default.json
├── crowdin.yml
├── definitions
├── assets.d.ts
├── btdGlobals.d.ts
├── globals.d.ts
└── pronouns
│ └── index.d.ts
├── docs
└── filters.md
├── jest.config.js
├── meta
├── better.tw_.png
├── debug-infos.png
├── en_desc.md
└── hotfixes.css
├── package-lock.json
├── package.json
├── safari
└── Better TweetDeck for Safari
│ ├── Better TweetDeck for Safari Extension
│ ├── Better_TweetDeck_for_Safari_Extension.entitlements
│ ├── Info.plist
│ └── SafariWebExtensionHandler.swift
│ ├── Better TweetDeck for Safari
│ ├── AppDelegate.swift
│ ├── Assets.xcassets
│ │ ├── AccentColor.colorset
│ │ │ └── Contents.json
│ │ ├── AppIcon.appiconset
│ │ │ ├── Contents.json
│ │ │ ├── icon-1024.png
│ │ │ ├── icon-128.png
│ │ │ ├── icon-16.png
│ │ │ ├── icon-256.png
│ │ │ ├── icon-32.png
│ │ │ ├── icon-512.png
│ │ │ └── icon-64.png
│ │ └── Contents.json
│ ├── Base.lproj
│ │ └── Main.storyboard
│ ├── Better_TweetDeck_for_Safari.entitlements
│ ├── Info.plist
│ └── ViewController.swift
│ └── BetterTDeck for TweetDeck.xcodeproj
│ ├── project.pbxproj
│ └── project.xcworkspace
│ └── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── src
├── _locales
│ ├── cs
│ │ └── messages.json
│ ├── de
│ │ └── messages.json
│ ├── en
│ │ └── messages.json
│ ├── fr
│ │ └── messages.json
│ ├── ja
│ │ └── messages.json
│ ├── nl
│ │ └── messages.json
│ ├── pt_BR
│ │ └── messages.json
│ └── ru
│ │ └── messages.json
├── assets
│ ├── accent-colors
│ │ ├── any.svg
│ │ ├── blue.svg
│ │ ├── green.svg
│ │ ├── orange.svg
│ │ ├── pink.svg
│ │ ├── purple.svg
│ │ ├── rainbow.svg
│ │ ├── red.svg
│ │ └── yellow.svg
│ ├── btd-logo-small.png
│ ├── btd-logo.png
│ ├── btd-stars
│ │ ├── btd-stars.eot
│ │ ├── btd-stars.svg
│ │ ├── btd-stars.ttf
│ │ ├── btd-stars.woff
│ │ └── btd-stars.woff2
│ ├── business-verified.svg
│ ├── clown-icon.svg
│ ├── column-preview
│ │ ├── clear-btn.png
│ │ ├── collapse-btn.png
│ │ ├── column-bg.png
│ │ └── no-icon.png
│ ├── crooked-icon.svg
│ ├── dark-themes
│ │ ├── default-dark.png
│ │ ├── light.png
│ │ ├── lights-out.png
│ │ └── old-dark.png
│ ├── dogears
│ │ ├── fav-heart.png
│ │ ├── fav-rt-heart.png
│ │ ├── fav-rt-star.png
│ │ ├── fav-star.png
│ │ └── rt.png
│ ├── dollar-icon.svg
│ ├── emoji-mart-data.json
│ ├── emoji-sheet-64.png
│ ├── filledStar.svg
│ ├── gov-verified.svg
│ ├── heart-icon.svg
│ ├── hexagone-mask.png
│ ├── icons
│ │ ├── icon-1024.png
│ │ ├── icon-128.png
│ │ ├── icon-16.png
│ │ ├── icon-256.png
│ │ ├── icon-32.png
│ │ ├── icon-48.png
│ │ ├── icon-512.png
│ │ ├── icon-64.png
│ │ ├── icon-96.png
│ │ ├── icon-beta-1024.png
│ │ ├── icon-beta-128.png
│ │ ├── icon-beta-16.png
│ │ ├── icon-beta-256.png
│ │ ├── icon-beta-32.png
│ │ ├── icon-beta-48.png
│ │ ├── icon-beta-512.png
│ │ ├── icon-beta-64.png
│ │ ├── icon-beta-96.png
│ │ ├── toolbar-icon-16.png
│ │ └── toolbar-icon-32.png
│ ├── logo-tweaks
│ │ ├── agender.svg
│ │ ├── androgyne.svg
│ │ ├── aromantic.svg
│ │ ├── asexual.svg
│ │ ├── bigender.svg
│ │ ├── bisexual.svg
│ │ ├── btd.svg
│ │ ├── demigirl.svg
│ │ ├── demiguy.svg
│ │ ├── deminonbinary.svg
│ │ ├── demisexual.svg
│ │ ├── enbian.svg
│ │ ├── genderfluid.svg
│ │ ├── genderqueer.svg
│ │ ├── intersex.svg
│ │ ├── lesbian.svg
│ │ ├── neutrois.svg
│ │ ├── non binary.svg
│ │ ├── omnisexual.svg
│ │ ├── pansexual.svg
│ │ ├── polyamory.svg
│ │ ├── polysexual.svg
│ │ ├── progress.svg
│ │ ├── rainbow.svg
│ │ └── trans.svg
│ ├── mutual-icon.svg
│ ├── nerd-checkmark.svg
│ ├── pronouns.json
│ ├── star.svg
│ ├── translator-icon.svg
│ ├── twitter-blue.svg
│ └── verified-icon.svg
├── background.ts
├── components
│ ├── conversationControlsButton.tsx
│ ├── emojiProvider.tsx
│ ├── fullscreenModalWrapper.tsx
│ ├── gifButton.css
│ ├── gifPicker
│ │ ├── gifButton.tsx
│ │ ├── gifPicker.tsx
│ │ ├── gifProvider.tsx
│ │ └── singleGif.tsx
│ ├── muteCatchesModal.tsx
│ ├── openBtdSettingsButton.tsx
│ ├── settings
│ │ ├── components
│ │ │ ├── avatarsShape.tsx
│ │ │ ├── badgesOnTopOfAvatars.tsx
│ │ │ ├── booleanSettingRow.tsx
│ │ │ ├── checkboxSelectSettingsRow.tsx
│ │ │ ├── columnSettingsPreview.tsx
│ │ │ ├── customAccentColor.tsx
│ │ │ ├── newFeatureBadge.tsx
│ │ │ ├── radioSelectSettingsRow.tsx
│ │ │ ├── settingsButton.tsx
│ │ │ ├── settingsCheckboxSelect.tsx
│ │ │ ├── settingsCss.tsx
│ │ │ ├── settingsCssEditor.tsx
│ │ │ ├── settingsModalComponents.tsx
│ │ │ ├── settingsRadioInput.tsx
│ │ │ ├── settingsRadioSelect.tsx
│ │ │ ├── settingsRow.tsx
│ │ │ ├── settingsSeparator.tsx
│ │ │ ├── settingsTextInput.tsx
│ │ │ ├── settingsTextInputWithAnnotation.tsx
│ │ │ ├── settingsToggle.tsx
│ │ │ ├── settingsTokensList.tsx
│ │ │ └── themeSelector.tsx
│ │ ├── menu
│ │ │ ├── settingsComposer.tsx
│ │ │ ├── settingsCredits.tsx
│ │ │ ├── settingsExportButton.tsx
│ │ │ ├── settingsGeneral.tsx
│ │ │ ├── settingsImportExport.tsx
│ │ │ ├── settingsLogo.tsx
│ │ │ ├── settingsSupport.tsx
│ │ │ ├── settingsTheme.tsx
│ │ │ ├── settingsTweetActions.tsx
│ │ │ └── settingsTweetsDisplay.tsx
│ │ ├── settingsComponents.tsx
│ │ ├── settingsContext.tsx
│ │ ├── settingsHelpers.ts
│ │ ├── settingsMenu.tsx
│ │ ├── settingsModal.css
│ │ ├── settingsModal.tsx
│ │ ├── settingsModalContent.tsx
│ │ ├── settingsStyles.ts
│ │ ├── settingsTweetContent.tsx
│ │ └── settingsTypes.ts
│ └── trans.tsx
├── content.ts
├── defineConfig.ts
├── features
│ ├── __tests__
│ │ ├── contentWarnings.spec.ts
│ │ ├── pronounsDisplay.spec.ts
│ │ └── spoilerHelpers.spec.ts
│ ├── addAccentColors.css
│ ├── addColumnButtons.css
│ ├── addColumnButtons.ts
│ ├── addTweetActions.css
│ ├── addTweetActions.ts
│ ├── addTweetMenuItems.css
│ ├── addTweetMenuItems.ts
│ ├── advancedMuteEngine.ts
│ ├── allowImagePaste.ts
│ ├── alwaysShowCharacterCount.css
│ ├── alwaysShowCharacterCount.ts
│ ├── autoSwitchThemes.ts
│ ├── badgesOnTopOfAvatars.css
│ ├── badgesOnTopOfAvatars.ts
│ ├── biggerEmoji.css
│ ├── biggerEmoji.ts
│ ├── blueVerified.css
│ ├── blueVerified.ts
│ ├── changeAvatarShape.css
│ ├── changeAvatarShape.ts
│ ├── changeScrollbars.css
│ ├── changeScrollbars.ts
│ ├── changeTimestampFormat.ts
│ ├── changeTweetActions.css
│ ├── changeTweetActions.ts
│ ├── circleTweetBorder.css
│ ├── circleTweetBorder.tsx
│ ├── collapseDms.css
│ ├── collapseDms.ts
│ ├── contentWarnings.css
│ ├── contentWarnings.ts
│ ├── contentWarningsHelpers.ts
│ ├── conversationControl.tsx
│ ├── customCss.ts
│ ├── emojiAutocompletion.tsx
│ ├── emojiPicker.css
│ ├── emojiPicker.tsx
│ ├── extendTwitterStatus.ts
│ ├── extendTwitterUser.ts
│ ├── freezeGifsProfilePictures.ts
│ ├── gifModals.css
│ ├── gifModals.tsx
│ ├── hideColumnIcons.css
│ ├── hideColumnIcons.ts
│ ├── hidePreviewButton.css
│ ├── hidePreviewButton.ts
│ ├── keepTweetedHashtags.ts
│ ├── lightsOut.css
│ ├── logoVariations.css
│ ├── logoVariations.tsx
│ ├── mainStyles.css
│ ├── makeSearchColumnsFirst.ts
│ ├── mediaWarnings.css
│ ├── mediaWarnings.tsx
│ ├── modernOverlays.css
│ ├── modernOverlays.ts
│ ├── muteNfts.css
│ ├── muteNfts.ts
│ ├── muteTwitterCircle.tsx
│ ├── mutesCatcher.tsx
│ ├── pauseColumnsOnHover.ts
│ ├── profileLabels.ts
│ ├── pronounsDisplay.ts
│ ├── redraftTweet.ts
│ ├── removeRedirection.ts
│ ├── renderCardsInColumnsNative.ts
│ ├── renderMediaAndQuotedTweets.ts
│ ├── replaceHeartsByStars.css
│ ├── replaceHeartsByStars.ts
│ ├── requireAltImages.css
│ ├── requireAltImages.ts
│ ├── revertToLegacyReplies.css
│ ├── revertToLegacyReplies.ts
│ ├── setupGifPicker.tsx
│ ├── showAvatarsInColumnsHeader.css
│ ├── showAvatarsInColumnsHeader.ts
│ ├── showTweetDogEars.css
│ ├── showTweetDogEars.ts
│ ├── smallerComposerButtons.css
│ ├── smallerComposerButtons.ts
│ ├── spoilerHelpers.ts
│ ├── themeTweaks.ts
│ ├── translateLanguageOverride.ts
│ ├── twemojiRegex.ts
│ ├── updateTabTitle.ts
│ ├── updateTwemojiRegex.ts
│ ├── useOriginalAspectRatio.css
│ ├── useOriginalAspectRatio.ts
│ └── usernameDisplay.ts
├── helpers
│ ├── asyncHelpers.ts
│ ├── browserHelpers.ts
│ ├── colorHelpers.ts
│ ├── communicationHelpers.ts
│ ├── domHelpers.tsx
│ ├── emojiHelpers.ts
│ ├── hookHelpers.ts
│ ├── modalHelpers.tsx
│ ├── mustacheHelpers.ts
│ ├── networkHelpers.ts
│ ├── runtimeTypeHelpers.ts
│ ├── tweetdeckHelpers.ts
│ ├── typeHelpers.ts
│ └── webExtensionHelpers.ts
├── inject.ts
├── options.tsx
├── optionsPage.ts
├── services
│ ├── backgroundGifRequests.ts
│ ├── backgroundSettings.ts
│ ├── chirpHandler.ts
│ ├── columnMediaSizeMonitor.ts
│ ├── debugMethods.ts
│ ├── injectInTD.ts
│ ├── monitorBtdModal.ts
│ ├── rollbackToLegacy.tsx
│ ├── setupBTDNotifications.tsx
│ ├── setupBTDRoot.tsx
│ └── setupSettings.tsx
└── types
│ ├── btdCommonTypes.ts
│ ├── btdMessageTypes.ts
│ ├── btdSettingsEnums.ts
│ ├── btdSettingsTypes.ts
│ └── tweetdeckTypes.ts
├── tools
├── createDefineConfig.ts
├── generateEmojiMartData.ts
├── generatePronouns.ts
├── latestTag.ts
├── makeMozillaSourceZip.ts
├── manifests
│ ├── chrome.js
│ ├── common.js
│ ├── commonHosts.js
│ ├── firefox-beta.js
│ ├── firefox.js
│ └── safari.js
├── release.ts
├── tsconfig.json
├── update_safari_files.js
└── uploadNightly.ts
├── tsconfig.json
├── webpack.config.js
└── webpack
├── btdWebpackPlugin.js
├── common.js
├── main.webpack.config.js
└── options.webpack.config.js
/.eslintignore:
--------------------------------------------------------------------------------
1 | !.eslintrc.js
2 | artifacts/
3 | dist/
4 | safari/
--------------------------------------------------------------------------------
/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | parser: '@typescript-eslint/parser',
3 | plugins: ['@typescript-eslint', 'unused-imports', 'simple-import-sort'],
4 | extends: [
5 | 'eslint:recommended',
6 | 'plugin:react/recommended',
7 | 'plugin:react-hooks/recommended',
8 | 'prettier',
9 | ],
10 | parserOptions: {
11 | ecmaVersion: 2020,
12 | ecmaFeatures: {
13 | jsx: true,
14 | },
15 | sourceType: 'module',
16 | },
17 | settings: {
18 | react: {
19 | version: 'detect',
20 | },
21 | },
22 | env: {
23 | node: true,
24 | },
25 | rules: {
26 | 'react-hooks/exhaustive-deps': [
27 | 'warn',
28 | {
29 | enableDangerousAutofixThisMayCauseInfiniteLoops: true,
30 | },
31 | ],
32 | },
33 | overrides: [
34 | {
35 | files: ['src/**/*'],
36 | env: {
37 | browser: true,
38 | node: false,
39 | },
40 | },
41 | {
42 | files: ['*.ts', '*.tsx'],
43 | rules: {
44 | 'react/prop-types': 0,
45 | 'no-redeclare': 0,
46 | 'no-unused-vars': 0,
47 | 'react/display-name': 0,
48 | 'simple-import-sort/imports': 2,
49 | 'unused-imports/no-unused-imports-ts': 2,
50 | 'no-use-before-define': 0,
51 | 'no-undef': 0,
52 | 'no-restricted-globals': 0,
53 | },
54 | },
55 | ],
56 | };
57 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # Set the default behavior, in case people don't have core.autocrlf set.
2 | * text eol=lf
3 |
4 | # Denote all files that are truly binary and should not be modified.
5 | *.png binary
6 | *.jpg binary
7 | *.gif binary
8 | *.eot binary
9 | *.woff binary
10 | *.ttf binary
11 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/bug_report.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Bug report
3 | about: Create a report to help us improve
4 | title: ''
5 | labels: bug
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Describe the bug**
11 | A clear and concise description of what the bug is.
12 |
13 | **To Reproduce**
14 | Steps to reproduce the behavior:
15 |
16 | 1. Go to '...'
17 | 2. Click on '....'
18 | 3. Scroll down to '....'
19 | 4. See error
20 |
21 | **Expected behavior**
22 | A clear and concise description of what you expected to happen.
23 |
24 | **Screenshots**
25 | If applicable, add screenshots to help explain your problem.
26 |
27 | **Desktop (please complete the following information):**
28 |
29 | - OS: [e.g. iOS]
30 | - Browser [e.g. chrome, safari]
31 | - Version [e.g. 22]
32 |
33 | **Additional context**
34 | Add any other context about the problem here.
35 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE/feature_request.md:
--------------------------------------------------------------------------------
1 | ---
2 | name: Feature request
3 | about: Suggest an idea for this project
4 | title: ''
5 | labels: feature
6 | assignees: ''
7 |
8 | ---
9 |
10 | **Disclaimer: I consider Better TweetDeck to be in a feature freeze state due to the impending release of the newer TweetDeck and will instead shift my focus on building an alternative client. As such, I will most likely close/ignore any feature request for the time being.
11 | See the following issue for details https://github.com/eramdam/BetterTweetDeck/issues/848**
12 |
--------------------------------------------------------------------------------
/.github/workflows/main.yml:
--------------------------------------------------------------------------------
1 | # This is a basic workflow to help you get started with Actions
2 |
3 | name: CI
4 |
5 | # Controls when the workflow will run
6 | on:
7 | # Triggers the workflow on push or pull request events but only for the main branch
8 | push:
9 | branches: [main, next]
10 |
11 | # Allows you to run this workflow manually from the Actions tab
12 | workflow_dispatch:
13 |
14 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel
15 | jobs:
16 | # This workflow contains a single job called "build"
17 | build:
18 | # The type of runner that the job will run on
19 | runs-on: ubuntu-latest
20 |
21 | # Steps represent a sequence of tasks that will be executed as part of the job
22 | steps:
23 | # Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
24 | - uses: actions/checkout@v3
25 |
26 | - name: Setup Node.js environment
27 | uses: actions/setup-node@v3
28 | with:
29 | node-version-file: ".nvmrc"
30 | - run: npm ci
31 |
32 | - name: Typecheck + lint
33 | run: npm test
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | dist/
4 | web-ext-artifacts/
5 | build/
6 | artifacts/*
7 | config/*.json
8 | !config/default.json
9 |
10 | # Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and Webstorm
11 | # Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839
12 | # From: https://github.com/github/gitignore/blob/master/Global/JetBrains.gitignore
13 | # User-specific stuff:
14 | .idea/**/workspace.xml
15 | .idea/**/tasks.xml
16 | .idea/dictionaries/*
17 | # Sensitive or high-churn files:
18 | .idea/**/dataSources/
19 | .idea/**/dataSources.ids
20 | .idea/**/dataSources.xml
21 | .idea/**/dataSources.local.xml
22 | .idea/**/sqlDataSources.xml
23 | .idea/**/dynamic.xml
24 | .idea/**/uiDesigner.xml
25 |
26 | *.log
27 | *.xcuserstate
28 | *.xcworkspacedata
29 | xcuserdata
30 | .yarn
31 |
--------------------------------------------------------------------------------
/.husky/.gitignore:
--------------------------------------------------------------------------------
1 | _
2 |
--------------------------------------------------------------------------------
/.husky/pre-commit:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | . "$(dirname "$0")/_/husky.sh"
3 |
4 | npx lint-staged
5 |
--------------------------------------------------------------------------------
/.npm-upgrade.json:
--------------------------------------------------------------------------------
1 | {
2 | "ignore": {
3 | "chalk": {
4 | "versions": "5.0.1",
5 | "reason": ""
6 | },
7 | "execa": {
8 | "versions": "6.*.*",
9 | "reason": "ESM"
10 | },
11 | "moduleraid": {
12 | "versions": "6.*.*",
13 | "reason": "not needed"
14 | }
15 | }
16 | }
17 |
--------------------------------------------------------------------------------
/.nvmrc:
--------------------------------------------------------------------------------
1 | v18
2 |
--------------------------------------------------------------------------------
/.prettierignore:
--------------------------------------------------------------------------------
1 | assets/
2 | dist/
3 | package.json
4 | public/*.html
5 | safari/
6 | emoji-mart-data.json
--------------------------------------------------------------------------------
/.prettierrc.json:
--------------------------------------------------------------------------------
1 | {
2 | "trailingComma": "es5",
3 | "tabWidth": 2,
4 | "semi": true,
5 | "printWidth": 100,
6 | "singleQuote": true,
7 | "bracketSpacing": false,
8 | "bracketSameLine": true,
9 | "arrowParens": "always",
10 | "overrides": [
11 | {
12 | "files": "*.css",
13 | "options": {
14 | "printWidth": 900
15 | }
16 | }
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | "recommendations": ["lokalise.i18n-ally", "dbaeumer.vscode-eslint"]
3 | }
4 |
--------------------------------------------------------------------------------
/.vscode/i18n-ally-custom-framework.yml:
--------------------------------------------------------------------------------
1 | # An array of strings which contain Language Ids defined by VS Code
2 | # You can check avaliable language ids here: https://code.visualstudio.com/docs/languages/overview#_language-id
3 | languageIds:
4 | - javascript
5 | - typescript
6 | - javascriptreact
7 | - typescriptreact
8 |
9 | # An array of RegExes to find the key usage. **The key should be captured in the first match group**.
10 | # You should unescape RegEx strings in order to fit in the YAML file
11 | # To help with this, you can use https://www.freeformatter.com/json-escape.html
12 | usageMatchRegex:
13 | # The following example shows how to detect `t("your.i18n.keys")`
14 | # the `{key}` will be placed by a proper keypath matching regex,
15 | # you can ignore it and use your own matching rules as well
16 | - 'Trans[\t\r\s]+id=[''"`]({key})[''"`]'
17 | - "getTransString\\('({key})'\\)"
18 | - '__MSG_({key})__'
19 |
20 | # An array of strings containing refactor templates.
21 | # The "$1" will be replaced by the keypath specified.
22 | # Optional: uncomment the following two lines to use
23 |
24 | refactorTemplates:
25 | - i18n.get("$1")
26 | -
27 | - getTransString('$1')
28 |
--------------------------------------------------------------------------------
/.vscode/settings.json:
--------------------------------------------------------------------------------
1 | {
2 | "editor.codeActionsOnSave": {
3 | "source.fixAll.eslint": "explicit"
4 | },
5 | "editor.formatOnSave": true,
6 | "editor.defaultFormatter": "esbenp.prettier-vscode",
7 | "[css]": {
8 | "editor.formatOnSave": true
9 | },
10 | "[json]": {
11 | "editor.formatOnSave": true,
12 | "editor.defaultFormatter": "vscode.json-language-features"
13 | },
14 | "[markdown]": {
15 | "editor.formatOnSave": true
16 | },
17 | "emmet.excludeLanguages": [],
18 | "emmet.includeLanguages": {
19 | "javascript": "javascriptreact",
20 | "markdown": "javascriptreact",
21 | "typescript": "typescriptreact"
22 | },
23 | "files.eol": "\n",
24 | "files.exclude": {
25 | "**/.DS_Store": true,
26 | "**/.git": true,
27 | "**/.hg": true,
28 | "**/.svn": true,
29 | "**/CVS": true,
30 | ".cache-loader": true
31 | },
32 | "i18n-ally.enabledFrameworks": ["chrome-ext", "custom"],
33 | "i18n-ally.extract.keyPrefix": "settings_",
34 | "i18n-ally.keystyle": "nested",
35 | "i18n-ally.localesPaths": ["src/_locales"],
36 | "i18n-ally.preferredDelimiter": "_",
37 | "movets.skipWarning": true,
38 | "search.exclude": {
39 | "**/bower_components": true,
40 | "**/node_modules": true
41 | },
42 | "typescript.format.insertSpaceAfterOpeningAndBeforeClosingNonemptyBraces": false,
43 | "typescript.preferences.useAliasesForRenames": false,
44 | "typescript.tsdk": "node_modules/typescript/lib"
45 | }
46 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2014 Damien Erambert
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy of
6 | this software and associated documentation files (the "Software"), to deal in
7 | the Software without restriction, including without limitation the rights to
8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 | the Software, and to permit persons to whom the Software is furnished to do so,
10 | subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 |
Better TweetDeck
4 |
5 | This fork works with [OldTweetDeck](https://github.com/dimdenGD/OldTweetDeck)! Install the same way as you did with OldTweetDeck. [Releases page](https://github.com/dimdenGD/BetterTweetDeck/releases).
6 |
--------------------------------------------------------------------------------
/artifacts/.gitkeep:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/artifacts/.gitkeep
--------------------------------------------------------------------------------
/config/default.json:
--------------------------------------------------------------------------------
1 | {
2 | "FirefoxId": "BetterTweetDeckDev@erambert.me",
3 | "Client": {
4 | "debug": false,
5 | "APIs": {
6 | "giphy": "",
7 | "tenor": ""
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/crowdin.yml:
--------------------------------------------------------------------------------
1 | files:
2 | - source: /src/_locales/en/*.json
3 | translation: /src/_locales/%two_letters_code%/%original_file_name%
4 |
--------------------------------------------------------------------------------
/definitions/assets.d.ts:
--------------------------------------------------------------------------------
1 | declare module '*.svg' {
2 | const content: string;
3 | export default content;
4 | }
5 |
6 | declare module '*.png' {
7 | const content: string;
8 | export default content;
9 | }
10 |
--------------------------------------------------------------------------------
/definitions/btdGlobals.d.ts:
--------------------------------------------------------------------------------
1 | import ModuleRaid from 'moduleraid';
2 |
3 | export {};
4 |
5 | declare global {
6 | interface Window {
7 | BTD?: {
8 | debug?: {
9 | jq?: JQueryStatic;
10 | mR: ModuleRaid;
11 | findMustache: typeof findMustache;
12 | getChirpFromElement: typeof getChirpFromElement;
13 | getChirpFromKey: typeof getChirpFromKey;
14 | getChirpFromKeyAlone: typeof getChirpFromKeyAlone;
15 | clearMuteCatches: typeof clearMuteCatches;
16 | };
17 | };
18 | }
19 | }
20 |
--------------------------------------------------------------------------------
/definitions/globals.d.ts:
--------------------------------------------------------------------------------
1 | interface DOMRectReadOnly {
2 | readonly x: number;
3 | readonly y: number;
4 | readonly width: number;
5 | readonly height: number;
6 | readonly top: number;
7 | readonly right: number;
8 | readonly bottom: number;
9 | readonly left: number;
10 | }
11 |
12 | declare global {}
13 |
14 | interface ResizeObserverCallback {
15 | (entries: ResizeObserverEntry[], observer: ResizeObserver): void;
16 | }
17 |
18 | interface ResizeObserverEntry {
19 | readonly target: Element;
20 | readonly contentRect: DOMRectReadOnly;
21 | }
22 |
23 | interface ResizeObserver {
24 | observe(target: Element): void;
25 | unobserve(target: Element): void;
26 | disconnect(): void;
27 | }
28 |
29 | declare var ResizeObserver: {
30 | prototype: ResizeObserver;
31 | new (callback: ResizeObserverCallback): ResizeObserver;
32 | };
33 |
--------------------------------------------------------------------------------
/definitions/pronouns/index.d.ts:
--------------------------------------------------------------------------------
1 | // https://github.com/katacarbix/pronouns.js/pull/11/
2 | declare module 'pronouns' {
3 | export type Pronoun = [
4 | subject: string,
5 | object: string,
6 | determiner: string,
7 | possessive: string,
8 | reflexive: string
9 | ];
10 | export type PartialPronoun = [string, string?, string?, string?, string?];
11 |
12 | export interface Pronouns {
13 | pronouns: Pronoun[];
14 | examples: Pronoun[];
15 |
16 | subject: string;
17 | object: string;
18 | determiner: string;
19 | possessive: string;
20 | reflexive: string;
21 |
22 | sub: string;
23 | obj: string;
24 | det: string;
25 | pos: string;
26 | ref: string;
27 |
28 | constructor(input: string): void;
29 |
30 | generateForms(i: number): void;
31 | generateExamples(): void;
32 | toString(): string;
33 | toUrl(): string;
34 | add(input: string): void;
35 | }
36 |
37 | export default function (input: string, log?: boolean): Pronouns;
38 |
39 | export function complete(input: string): string[];
40 |
41 | export const table: Pronoun[];
42 |
43 | interface Util {
44 | logging: boolean;
45 | tableFrontFilter: (q: PartialPronoun, table: Pronoun[]) => Pronoun[];
46 | tableEndFilter: (q: PartialPronoun, table: Pronoun[]) => Pronoun[];
47 | tableLookup: (q: PartialPronoun, table: Pronoun[]) => Pronoun | undefined;
48 | shortestUnambiguousForwardPath: (table: Pronoun[], row: PartialPronoun) => PartialPronoun;
49 | shortestUnambiguousEllipsesPath: (table: Pronoun[], row: PartialPronoun) => PartialPronoun;
50 | shortestUnambiguousPath: (table: Pronoun[], row: PartialPronoun) => PartialPronoun;
51 | abbreviate: (table: Pronoun[]) => string[][];
52 | sanitizeSet: (p: PartialPronoun[], table: Pronoun[]) => Pronoun[];
53 | expandString: (str: string, table: Pronoun[]) => Pronoun[];
54 | arrFormat: (x: T | T[]) => T[];
55 | capitalize: (str: string) => string;
56 | rowsEqual: (a: PartialPronoun, b: Pronoun) => boolean;
57 | }
58 |
59 | export const util: Util;
60 |
61 | export const abbreviated: string[][];
62 | }
63 |
--------------------------------------------------------------------------------
/jest.config.js:
--------------------------------------------------------------------------------
1 | /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
2 | module.exports = {
3 | preset: 'ts-jest',
4 | testEnvironment: 'node',
5 | globals: {'ts-jest': {isolatedModules: true}},
6 | };
7 |
--------------------------------------------------------------------------------
/meta/better.tw_.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/meta/better.tw_.png
--------------------------------------------------------------------------------
/meta/debug-infos.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/meta/debug-infos.png
--------------------------------------------------------------------------------
/meta/en_desc.md:
--------------------------------------------------------------------------------
1 | Improve your experience on TweetDeck web with tons of features!
2 |
3 | More informations on https://better.tw
4 |
5 | Report bugs here:
6 | https://github.com/eramdam/BetterTweetDeck/issues
7 |
8 | Source code:
9 | https://github.com/eramdam/BetterTweetDeck
10 |
11 | Follow @BetterTDeck on Twitter for news/support
12 |
--------------------------------------------------------------------------------
/meta/hotfixes.css:
--------------------------------------------------------------------------------
1 | /**
2 | * This whole file is going to be embedded into Better TweetDeck as a "hotfix" file.
3 | *
4 | * Don't.
5 | *
6 | * Mess.
7 | *
8 | * Up.
9 | *
10 | * Anything.
11 | *
12 | * In.
13 | *
14 | * There.
15 | *
16 | * Please.
17 | *
18 | * Thanks :)
19 | */
20 |
21 | .js-add-emojis.padding-v--9.js-add-emojis {
22 | padding-top: 6px !important;
23 | padding-left: 12px !important;
24 | padding-right: 12px !important;
25 | padding-bottom: 5px !important;
26 | }
27 |
28 | .js-add-emojis.padding-v--9.js-add-emojis .btd-emoji-icon {
29 | font-size: 18px !important;
30 | }
31 |
32 | .btd__small_icns_compose .js-add-emojis.padding-v--9.js-add-emojis .btd-emoji-icon {
33 | transform: translateY(-2px);
34 | }
35 |
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari Extension/Better_TweetDeck_for_Safari_Extension.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari Extension/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleDisplayName
8 | Better TweetDeck for Safari Extension
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleVersion
22 | 2312181630
23 | ITSAppUsesNonExemptEncryption
24 |
25 | LSMinimumSystemVersion
26 | $(MACOSX_DEPLOYMENT_TARGET)
27 | NSExtension
28 |
29 | NSExtensionPointIdentifier
30 | com.apple.Safari.web-extension
31 | NSExtensionPrincipalClass
32 | $(PRODUCT_MODULE_NAME).SafariWebExtensionHandler
33 |
34 |
35 |
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari Extension/SafariWebExtensionHandler.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SafariWebExtensionHandler.swift
3 | // Better TweetDeck for Safari Extension
4 | //
5 | // Created by Damien Erambert on 1/16/21.
6 | //
7 |
8 | import SafariServices
9 | import os.log
10 |
11 | let SFExtensionMessageKey = "message"
12 |
13 | class SafariWebExtensionHandler: NSObject, NSExtensionRequestHandling {
14 |
15 | func beginRequest(with context: NSExtensionContext) {
16 | let item = context.inputItems[0] as! NSExtensionItem
17 | let message = item.userInfo?[SFExtensionMessageKey]
18 | os_log(.default, "Received message from browser.runtime.sendNativeMessage: %@", message as! CVarArg)
19 |
20 | let response = NSExtensionItem()
21 | response.userInfo = [ SFExtensionMessageKey: [ "Response to": message ] ]
22 |
23 | context.completeRequest(returningItems: [response], completionHandler: nil)
24 | }
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Better TweetDeck for Safari
4 | //
5 | // Created by Damien Erambert on 1/16/21.
6 | //
7 |
8 | import Cocoa
9 |
10 | @main
11 | class AppDelegate: NSObject, NSApplicationDelegate {
12 |
13 | func applicationDidFinishLaunching(_ notification: Notification) {
14 | // Insert code here to initialize your application
15 | }
16 |
17 | func applicationWillTerminate(_ notification: Notification) {
18 | // Insert code here to tear down your application
19 | }
20 |
21 | func applicationShouldTerminateAfterLastWindowClosed(_ sender: NSApplication) -> Bool {
22 | return true
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AccentColor.colorset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "colors" : [
3 | {
4 | "idiom" : "universal"
5 | }
6 | ],
7 | "info" : {
8 | "author" : "xcode",
9 | "version" : 1
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "filename" : "icon-16.png",
5 | "idiom" : "mac",
6 | "scale" : "1x",
7 | "size" : "16x16"
8 | },
9 | {
10 | "filename" : "icon-32.png",
11 | "idiom" : "mac",
12 | "scale" : "2x",
13 | "size" : "16x16"
14 | },
15 | {
16 | "filename" : "icon-32.png",
17 | "idiom" : "mac",
18 | "scale" : "1x",
19 | "size" : "32x32"
20 | },
21 | {
22 | "filename" : "icon-64.png",
23 | "idiom" : "mac",
24 | "scale" : "2x",
25 | "size" : "32x32"
26 | },
27 | {
28 | "filename" : "icon-128.png",
29 | "idiom" : "mac",
30 | "scale" : "1x",
31 | "size" : "128x128"
32 | },
33 | {
34 | "filename" : "icon-256.png",
35 | "idiom" : "mac",
36 | "scale" : "2x",
37 | "size" : "128x128"
38 | },
39 | {
40 | "filename" : "icon-256.png",
41 | "idiom" : "mac",
42 | "scale" : "1x",
43 | "size" : "256x256"
44 | },
45 | {
46 | "filename" : "icon-512.png",
47 | "idiom" : "mac",
48 | "scale" : "2x",
49 | "size" : "256x256"
50 | },
51 | {
52 | "filename" : "icon-512.png",
53 | "idiom" : "mac",
54 | "scale" : "1x",
55 | "size" : "512x512"
56 | },
57 | {
58 | "filename" : "icon-1024.png",
59 | "idiom" : "mac",
60 | "scale" : "2x",
61 | "size" : "512x512"
62 | }
63 | ],
64 | "info" : {
65 | "author" : "xcode",
66 | "version" : 1
67 | }
68 | }
69 |
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-1024.png
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-128.png
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-16.png
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-256.png
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-32.png
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-512.png
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/AppIcon.appiconset/icon-64.png
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "author" : "xcode",
4 | "version" : 1
5 | }
6 | }
7 |
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Better_TweetDeck_for_Safari.entitlements:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | com.apple.security.app-sandbox
6 |
7 | com.apple.security.files.user-selected.read-only
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | $(DEVELOPMENT_LANGUAGE)
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIconFile
10 |
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | $(PRODUCT_BUNDLE_PACKAGE_TYPE)
19 | CFBundleShortVersionString
20 | $(MARKETING_VERSION)
21 | CFBundleVersion
22 | 2312181630
23 | ITSAppUsesNonExemptEncryption
24 |
25 | LSApplicationCategoryType
26 | public.app-category.social-networking
27 | LSMinimumSystemVersion
28 | $(MACOSX_DEPLOYMENT_TARGET)
29 | NSMainStoryboardFile
30 | Main
31 | NSPrincipalClass
32 | NSApplication
33 |
34 |
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/Better TweetDeck for Safari/ViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ViewController.swift
3 | // Better TweetDeck for Safari
4 | //
5 | // Created by Damien Erambert on 1/16/21.
6 | //
7 |
8 | import Cocoa
9 | import SafariServices.SFSafariApplication
10 | import SafariServices.SFSafariExtensionManager
11 |
12 | let appName = "Better TDeck for TweetDeck"
13 | let extensionBundleIdentifier = "me.erambert.bettertweetdeck-safari.extension"
14 |
15 | class ViewController: NSViewController {
16 |
17 | @IBOutlet var appNameLabel: NSTextField!
18 |
19 | override func viewDidLoad() {
20 | super.viewDidLoad()
21 | self.appNameLabel.stringValue = appName
22 | SFSafariExtensionManager.getStateOfSafariExtension(withIdentifier: extensionBundleIdentifier) { (state, error) in
23 | guard let state = state, error == nil else {
24 | // Insert code to inform the user that something went wrong.
25 | return
26 | }
27 |
28 | DispatchQueue.main.async {
29 | if (state.isEnabled) {
30 | self.appNameLabel.stringValue = "\(appName)'s extension is currently on."
31 | } else {
32 | self.appNameLabel.stringValue = "\(appName)'s extension is currently off. You can turn it on in Safari Extensions preferences."
33 | }
34 | }
35 | }
36 | }
37 |
38 | @IBAction func openSafariExtensionPreferences(_ sender: AnyObject?) {
39 | SFSafariApplication.showPreferencesForExtension(withIdentifier: extensionBundleIdentifier) { error in
40 | guard error == nil else {
41 | // Insert code to inform the user that something went wrong.
42 | return
43 | }
44 |
45 | DispatchQueue.main.async {
46 | NSApplication.shared.terminate(nil)
47 | }
48 | }
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/safari/Better TweetDeck for Safari/BetterTDeck for TweetDeck.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/src/_locales/cs/messages.json:
--------------------------------------------------------------------------------
1 | {}
2 |
--------------------------------------------------------------------------------
/src/_locales/nl/messages.json:
--------------------------------------------------------------------------------
1 | {
2 | "app_desc": {
3 | "message": "Neem TweetDeck naar het volgende level!"
4 | },
5 | "app_name": {
6 | "message": "Better TweetDeck"
7 | },
8 | "settings_title": {
9 | "message": "Better TweetDeck"
10 | },
11 | "settings_show_cards_inside_columns": {
12 | "message": "Toon tweet kaarten in kolommen"
13 | },
14 | "settings_show_profile_badges_on_top_of_avatars": {
15 | "message": "Toon profielbadges boven aan avatars"
16 | },
17 | "settings_collapse_read_dms": {
18 | "message": "Gelezen privéberichten inklappen"
19 | },
20 | "settings_freeze_gifs_in_profile_pictures": {
21 | "message": "GIFs bevriezen in profielfoto's"
22 | },
23 | "settings_remove_t_co_redirection_on_links": {
24 | "message": "Verwijder t.co omleiding op links"
25 | },
26 | "settings_make_buttons_smaller_in_the_composer": {
27 | "message": "Knoppen kleiner maken in het opstelvenster"
28 | },
29 | "settings_reflect_new_tweets_and_dms_in_the_tabs_title": {
30 | "message": "Nieuwe tweets en DMs in de tab titel reflecteren"
31 | },
32 | "settings_auto_switch_light_theme": {
33 | "message": "Schakel over naar lichte thema wanneer OS in licht-modus is"
34 | },
35 | "settings_scrollbar_default": {
36 | "message": "Standaard"
37 | },
38 | "settings_scrollbar_hidden": {
39 | "message": "Verborgen"
40 | },
41 | "settings_style_of_scrollbars": {
42 | "message": "Stijl van de schuifbalken"
43 | },
44 | "settings_show_clear_button_column": {
45 | "message": "Toon de \"Wissen\" knop in kolomkop"
46 | },
47 | "settings_show_collapse_button_in_columns_header": {
48 | "message": "Toon de \"Wissen\" knop in kolomkop"
49 | },
50 | "settings_hide_icons_on_top_of_columns": {
51 | "message": "Pictogrammen op de bovenkant van kolommen verbergen"
52 | }
53 | }
54 |
--------------------------------------------------------------------------------
/src/assets/accent-colors/any.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/accent-colors/blue.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/accent-colors/green.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/accent-colors/pink.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/accent-colors/purple.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/accent-colors/rainbow.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/assets/btd-logo-small.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/btd-logo-small.png
--------------------------------------------------------------------------------
/src/assets/btd-logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/btd-logo.png
--------------------------------------------------------------------------------
/src/assets/btd-stars/btd-stars.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/btd-stars/btd-stars.eot
--------------------------------------------------------------------------------
/src/assets/btd-stars/btd-stars.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/btd-stars/btd-stars.ttf
--------------------------------------------------------------------------------
/src/assets/btd-stars/btd-stars.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/btd-stars/btd-stars.woff
--------------------------------------------------------------------------------
/src/assets/btd-stars/btd-stars.woff2:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/btd-stars/btd-stars.woff2
--------------------------------------------------------------------------------
/src/assets/column-preview/clear-btn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/column-preview/clear-btn.png
--------------------------------------------------------------------------------
/src/assets/column-preview/collapse-btn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/column-preview/collapse-btn.png
--------------------------------------------------------------------------------
/src/assets/column-preview/column-bg.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/column-preview/column-bg.png
--------------------------------------------------------------------------------
/src/assets/column-preview/no-icon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/column-preview/no-icon.png
--------------------------------------------------------------------------------
/src/assets/dark-themes/default-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/dark-themes/default-dark.png
--------------------------------------------------------------------------------
/src/assets/dark-themes/light.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/dark-themes/light.png
--------------------------------------------------------------------------------
/src/assets/dark-themes/lights-out.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/dark-themes/lights-out.png
--------------------------------------------------------------------------------
/src/assets/dark-themes/old-dark.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/dark-themes/old-dark.png
--------------------------------------------------------------------------------
/src/assets/dogears/fav-heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/dogears/fav-heart.png
--------------------------------------------------------------------------------
/src/assets/dogears/fav-rt-heart.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/dogears/fav-rt-heart.png
--------------------------------------------------------------------------------
/src/assets/dogears/fav-rt-star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/dogears/fav-rt-star.png
--------------------------------------------------------------------------------
/src/assets/dogears/fav-star.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/dogears/fav-star.png
--------------------------------------------------------------------------------
/src/assets/dogears/rt.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/dogears/rt.png
--------------------------------------------------------------------------------
/src/assets/emoji-sheet-64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/emoji-sheet-64.png
--------------------------------------------------------------------------------
/src/assets/filledStar.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/heart-icon.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/hexagone-mask.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/hexagone-mask.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-1024.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-128.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-16.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-256.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-32.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-48.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-512.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-64.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-96.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-beta-1024.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-beta-1024.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-beta-128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-beta-128.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-beta-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-beta-16.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-beta-256.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-beta-256.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-beta-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-beta-32.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-beta-48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-beta-48.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-beta-512.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-beta-512.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-beta-64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-beta-64.png
--------------------------------------------------------------------------------
/src/assets/icons/icon-beta-96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/icon-beta-96.png
--------------------------------------------------------------------------------
/src/assets/icons/toolbar-icon-16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/toolbar-icon-16.png
--------------------------------------------------------------------------------
/src/assets/icons/toolbar-icon-32.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/dimdenGD/BetterTweetDeck/641e4901108dfa7526340d78b7ce5a910de435fd/src/assets/icons/toolbar-icon-32.png
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/agender.svg:
--------------------------------------------------------------------------------
1 |
26 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/androgyne.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/aromantic.svg:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/asexual.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/bigender.svg:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/bisexual.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/btd.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/demigirl.svg:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/demiguy.svg:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/deminonbinary.svg:
--------------------------------------------------------------------------------
1 |
24 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/demisexual.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/enbian.svg:
--------------------------------------------------------------------------------
1 |
23 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/genderfluid.svg:
--------------------------------------------------------------------------------
1 |
28 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/genderqueer.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/lesbian.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/neutrois.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/non binary.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/omnisexual.svg:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/pansexual.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/polyamory.svg:
--------------------------------------------------------------------------------
1 |
20 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/polysexual.svg:
--------------------------------------------------------------------------------
1 |
19 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/progress.svg:
--------------------------------------------------------------------------------
1 |
26 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/rainbow.svg:
--------------------------------------------------------------------------------
1 |
22 |
--------------------------------------------------------------------------------
/src/assets/logo-tweaks/trans.svg:
--------------------------------------------------------------------------------
1 |
21 |
--------------------------------------------------------------------------------
/src/assets/mutual-icon.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/assets/star.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/src/components/fullscreenModalWrapper.tsx:
--------------------------------------------------------------------------------
1 | import React, {FC, ReactNode} from 'react';
2 |
3 | import {Handler} from '../helpers/typeHelpers';
4 |
5 | interface FullscreenModalWrapperProps {
6 | onClose: Handler;
7 | children: ReactNode;
8 | }
9 |
10 | export const FullscreenModal: FC = (props) => {
11 | return (
12 |
13 |
14 |
15 |
20 |
21 |
22 |
28 |
29 |
30 |
38 | {props.children}
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 | );
49 | };
50 |
--------------------------------------------------------------------------------
/src/components/gifButton.css:
--------------------------------------------------------------------------------
1 | .btd-gif-button {
2 | transition-property: transform, opacity;
3 | transition-duration: 300ms;
4 | transition-timing-function: ease;
5 | float: left;
6 |
7 | &.-visible {
8 | opacity: 1;
9 | transform: translateX(0);
10 | }
11 | }
12 |
13 | .btd-gif-button {
14 | font-weight: bold;
15 | font-size: 10px;
16 | border-radius: 3px;
17 | padding: 2px 6px;
18 | border: 1px solid currentColor;
19 | cursor: pointer;
20 | overflow: hidden;
21 | position: absolute;
22 | left: 10px;
23 | bottom: 10px;
24 | z-index: 0;
25 | opacity: 0;
26 | transition-property: color, opacity;
27 | user-select: none;
28 | pointer-events: none;
29 |
30 | &:hover {
31 | color: #616161 !important;
32 | }
33 | }
34 |
35 | .btd-gif-button.-visible {
36 | opacity: 1;
37 | pointer-events: auto;
38 | }
39 |
40 | .btd-gif-button.btd-gif-button:hover {
41 | color: #616161;
42 | }
43 |
--------------------------------------------------------------------------------
/src/components/gifPicker/gifButton.tsx:
--------------------------------------------------------------------------------
1 | import '../gifButton.css';
2 |
3 | import React, {FC} from 'react';
4 |
5 | import {Handler} from '../../helpers/typeHelpers';
6 |
7 | export const BTDGifButton: FC<{
8 | onClick: Handler;
9 | }> = (props) => {
10 | const d = new Date();
11 | const fool = d.getDate() === 1 && d.getMonth() === 3;
12 | const GIFText = fool ? 'JIF' : 'GIF';
13 |
14 | return (
15 |
16 | {GIFText}
17 |
18 | );
19 | };
20 |
--------------------------------------------------------------------------------
/src/components/gifPicker/singleGif.tsx:
--------------------------------------------------------------------------------
1 | import React, {FC} from 'react';
2 |
3 | import {Handler} from '../../helpers/typeHelpers';
4 |
5 | export interface GifItemProps {
6 | previewUrl: string;
7 | onClick: Handler;
8 | }
9 | export const BTDGifItem: FC = (props) => {
10 | return (
11 |
15 |

24 |
25 | );
26 | };
27 |
--------------------------------------------------------------------------------
/src/components/openBtdSettingsButton.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | export const BTDSettingsButton = () => {
4 | return (
5 |
9 |
10 |
11 |
12 |
13 | BTD Settings
14 |
15 |
16 | );
17 | };
18 |
--------------------------------------------------------------------------------
/src/components/settings/components/badgesOnTopOfAvatars.tsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 |
3 | import {BaseSettingsProps} from '../settingsTypes';
4 | import {BooleanSettingsRow} from './booleanSettingRow';
5 |
6 | interface BadgesOnTopOfAvatarsProps extends BaseSettingsProps<'badgesOnTopOfAvatars'> {}
7 |
8 | export function BadgesOnTopOfAvatars(props: BadgesOnTopOfAvatarsProps) {
9 | return (
10 |
14 | Show badges on top of avatars
15 |
16 | );
17 | }
18 |
--------------------------------------------------------------------------------
/src/components/settings/components/booleanSettingRow.tsx:
--------------------------------------------------------------------------------
1 | import {css, cx} from '@emotion/css';
2 | import React, {PropsWithChildren} from 'react';
3 |
4 | import {HandlerOf} from '../../../helpers/typeHelpers';
5 | import {useSettingsSearch} from '../settingsContext';
6 | import {reactElementToString} from '../settingsHelpers';
7 | import {settingsDisabled} from '../settingsStyles';
8 | import {featureBadgeClassname, NewFeatureBadge, NewFeatureBadgeProps} from './newFeatureBadge';
9 | import {SettingsRow, SettingsRowContent} from './settingsRow';
10 | import {SettingsToggle} from './settingsToggle';
11 |
12 | interface BooleanSettingsRowProps extends Partial {
13 | initialValue: boolean;
14 | onChange: HandlerOf;
15 | settingsKey: string;
16 | className?: string;
17 | alignToTheLeft?: boolean;
18 | noPaddingTop?: boolean;
19 | disabled?: boolean;
20 | ignoreInSearch?: boolean;
21 | }
22 |
23 | export function BooleanSettingsRow(props: PropsWithChildren) {
24 | const {renderAndAddtoIndex} = useSettingsSearch();
25 | const render = () => (
26 |
30 |
39 |
44 | {props.children}
45 | {props.introducedIn && (
46 |
47 | )}
48 |
49 |
50 |
51 | );
52 |
53 | if (!props.ignoreInSearch) {
54 | renderAndAddtoIndex({
55 | keywords: [reactElementToString(props.children)],
56 | key: props.settingsKey,
57 | render: () => render(),
58 | });
59 | }
60 |
61 | return render();
62 | }
63 |
--------------------------------------------------------------------------------
/src/components/settings/components/newFeatureBadge.tsx:
--------------------------------------------------------------------------------
1 | import {css, cx} from '@emotion/css';
2 | import React, {FC, useMemo} from 'react';
3 | import semver from 'semver';
4 |
5 | import {getExtensionVersion} from '../../../helpers/webExtensionHelpers';
6 |
7 | export interface NewFeatureBadgeProps {
8 | introducedIn: string;
9 | }
10 |
11 | const currentVersion = semver.coerce(getExtensionVersion());
12 |
13 | export const featureBadgeClassname = 'btd-feature-badge';
14 |
15 | export const NewFeatureBadge: FC = (props) => {
16 | const featureVersion = semver.coerce(props.introducedIn);
17 | const maxMinorDiff = 3;
18 |
19 | const isOutdated = useMemo(() => {
20 | if (!currentVersion || !featureVersion) {
21 | return true;
22 | }
23 |
24 | if (currentVersion.major > featureVersion.major) {
25 | return true;
26 | }
27 |
28 | const minorDiff = currentVersion.minor - featureVersion.minor;
29 | if (minorDiff > maxMinorDiff) {
30 | return true;
31 | }
32 |
33 | return false;
34 | }, [featureVersion, maxMinorDiff]);
35 |
36 | if (isOutdated) {
37 | return null;
38 | }
39 |
40 | return (
41 |
58 | NEW
59 |
60 | );
61 | };
62 |
--------------------------------------------------------------------------------
/src/components/settings/components/radioSelectSettingsRow.tsx:
--------------------------------------------------------------------------------
1 | import {css, cx} from '@emotion/css';
2 | import React, {PropsWithChildren} from 'react';
3 |
4 | import {BTDSettings} from '../../../types/btdSettingsTypes';
5 | import {useSettingsSearch} from '../settingsContext';
6 | import {reactElementToString} from '../settingsHelpers';
7 | import {SettingsRadioSettingSelect, SettingsRadioSettingsSelectProps} from './settingsRadioSelect';
8 | import {SettingsRow, SettingsRowContent, SettingsRowTitle} from './settingsRow';
9 |
10 | function RadioSelectSettingsRow(
11 | props: PropsWithChildren>
12 | ) {
13 | return (
14 |
25 | {props.children}
26 |
32 |
33 | settingsKey={props.settingsKey}
34 | onChange={props.onChange}
35 | initialValue={props.initialValue}
36 | fields={props.fields}
37 | />
38 |
39 |
40 | );
41 | }
42 |
43 | export function BTDRadioSelectSettingsRow(
44 | props: PropsWithChildren>
45 | ) {
46 | const {renderAndAddtoIndex} = useSettingsSearch();
47 | return (
48 | <>
49 | {renderAndAddtoIndex({
50 | key: props.settingsKey,
51 | keywords: props.fields.map((f) => reactElementToString(f.searchTerm || f.label)),
52 | render: (newSettings) =>
53 | RadioSelectSettingsRow({...props, initialValue: newSettings[props.settingsKey]}),
54 | })}
55 | >
56 | );
57 | }
58 |
--------------------------------------------------------------------------------
/src/components/settings/components/settingsButton.tsx:
--------------------------------------------------------------------------------
1 | import React, {PropsWithChildren} from 'react';
2 |
3 | import {Handler} from '../../../helpers/typeHelpers';
4 |
5 | interface SettingsButtonProps {
6 | onClick: Handler;
7 | variant?: 'primary' | 'secondary';
8 | disabled?: boolean;
9 | }
10 | export function SettingsButton(props: PropsWithChildren) {
11 | return (
12 |
18 | );
19 | }
20 |
--------------------------------------------------------------------------------
/src/components/settings/components/settingsCss.tsx:
--------------------------------------------------------------------------------
1 | import React, {FC} from 'react';
2 |
3 | import {BTDSettings} from '../../../types/btdSettingsTypes';
4 | import {getTransString} from '../../trans';
5 | import {SettingsMenuSectionProps} from '../settingsComponents';
6 | import {useSettingsSearch} from '../settingsContext';
7 | import {SettingsCssEditor} from './settingsCssEditor';
8 |
9 | export const SettingsCss: FC = (props) => {
10 | const {makeOnSettingsChange, setEditorHasErrors} = props;
11 | const {renderAndAddtoIndex} = useSettingsSearch();
12 | const renderEditor = (newSettings: BTDSettings) => (
13 | makeOnSettingsChange('customCss')(val)}
15 | onErrorChange={setEditorHasErrors}
16 | value={newSettings.customCss}>
17 | );
18 |
19 | return (
20 | <>
21 | {renderAndAddtoIndex({
22 | key: 'custom_css',
23 | keywords: [getTransString('settings_custom_css')],
24 | render: renderEditor,
25 | })}
26 | >
27 | );
28 | };
29 |
--------------------------------------------------------------------------------
/src/components/settings/components/settingsModalComponents.tsx:
--------------------------------------------------------------------------------
1 | import {cx} from '@emotion/css';
2 | import React, {PropsWithChildren} from 'react';
3 |
4 | type defaultProps = PropsWithChildren<{}>;
5 |
6 | export function SettingsModalWrapper(props: defaultProps) {
7 | return {props.children}
;
8 | }
9 | export function SettingsHeader(props: defaultProps) {
10 | return {props.children}
;
11 | }
12 | export function SettingsSidebar(props: defaultProps) {
13 | return {props.children}
;
14 | }
15 | export function SettingsContent(props: defaultProps) {
16 | return {props.children}
;
17 | }
18 | export function SettingsFooter(
19 | props: defaultProps & {
20 | className?: string;
21 | }
22 | ) {
23 | return {props.children}
;
24 | }
25 | export function SettingsFooterLabel(props: defaultProps) {
26 | return {props.children}
;
27 | }
28 |
--------------------------------------------------------------------------------
/src/components/settings/components/settingsRadioInput.tsx:
--------------------------------------------------------------------------------
1 | import {css} from '@emotion/css';
2 | import React, {PropsWithChildren} from 'react';
3 |
4 | import {Handler} from '../../../helpers/typeHelpers';
5 |
6 | const mainInputStyles = css`
7 | appearance: none;
8 | width: 15px;
9 | height: 15px;
10 | border: 1px solid var(--twitter-blue);
11 | background: transparent;
12 | outline: 0;
13 | border-radius: 100%;
14 |
15 | &:checked,
16 | &[checked] {
17 | box-shadow: inset 0 0 0 3px var(--settings-modal-background),
18 | inset 0 0 0 8px var(--twitter-blue);
19 | }
20 | `;
21 |
22 | interface SettingsRadioSelectFieldProps {
23 | name: string;
24 | id: string;
25 | defaultChecked: boolean;
26 | onChange: Handler;
27 | className?: string;
28 | isDisabled?: boolean;
29 | }
30 | export function SettingsRadioInput(props: PropsWithChildren) {
31 | return (
32 |
33 |
42 |
43 |
44 | );
45 | }
46 |
--------------------------------------------------------------------------------
/src/components/settings/components/settingsRadioSelect.tsx:
--------------------------------------------------------------------------------
1 | import {css, cx} from '@emotion/css';
2 | import React, {ReactNode} from 'react';
3 |
4 | import {HandlerOf} from '../../../helpers/typeHelpers';
5 | import {BTDSettings} from '../../../types/btdSettingsTypes';
6 | import {settingsDisabled} from '../settingsStyles';
7 | import {SettingsRadioInput} from './settingsRadioInput';
8 |
9 | export interface SettingsRadioSettingsSelectProps {
10 | fields: ReadonlyArray<{
11 | label: ReactNode;
12 | searchTerm?: string;
13 | value: S[T];
14 | }>;
15 | initialValue: S[T];
16 | settingsKey: T;
17 | onChange: HandlerOf;
18 | ignoreSearch?: boolean;
19 | className?: string;
20 | isDisabled?: boolean;
21 | }
22 |
23 | const wrapperStyles = css`
24 | padding-top: 4px;
25 | display: grid;
26 | grid-auto-flow: row;
27 | grid-row-gap: 10px;
28 | grid-auto-columns: 100%;
29 |
30 | input + label {
31 | padding-left: 10px;
32 | }
33 | `;
34 |
35 | export function SettingsRadioSettingSelect(
36 | props: SettingsRadioSettingsSelectProps
37 | ) {
38 | return (
39 |
40 | {props.fields.map((field) => {
41 | return (
42 | props.onChange(field.value)}
48 | isDisabled={props.isDisabled}>
49 | {field.label}
50 |
51 | );
52 | })}
53 |
54 | );
55 | }
56 |
57 | export function BTDSettingsRadioSettingSelect(
58 | props: SettingsRadioSettingsSelectProps
59 | ) {
60 | return SettingsRadioSettingSelect(props);
61 | }
62 |
--------------------------------------------------------------------------------
/src/components/settings/components/settingsRow.tsx:
--------------------------------------------------------------------------------
1 | import {css, cx} from '@emotion/css';
2 | import React from 'react';
3 | import {PropsWithChildren} from 'react';
4 |
5 | import {settingsDisabled, settingsRow, settingsRowTitle} from '../settingsStyles';
6 |
7 | type SettingsRowProps = PropsWithChildren<{className?: string}>;
8 |
9 | export function SettingsRow(
10 | props: SettingsRowProps & {disabled?: boolean; stretch?: boolean; noPaddingTop?: boolean}
11 | ) {
12 | const stretch = props.stretch ?? true;
13 | return (
14 |
28 | {props.children}
29 |
30 | );
31 | }
32 | export function SettingsRowTitle(props: SettingsRowProps) {
33 | return {props.children}
;
34 | }
35 | export function SettingsRowContent(props: SettingsRowProps) {
36 | return {props.children}
;
37 | }
38 |
--------------------------------------------------------------------------------
/src/components/settings/components/settingsSeparator.tsx:
--------------------------------------------------------------------------------
1 | import {css} from '@emotion/css';
2 | import React from 'react';
3 |
4 | import {settingsRow} from '../settingsStyles';
5 |
6 | export function SettingsSeparator() {
7 | return (
8 |
21 | );
22 | }
23 |
--------------------------------------------------------------------------------
/src/components/settings/components/settingsTextInput.tsx:
--------------------------------------------------------------------------------
1 | import {css, cx} from '@emotion/css';
2 | import React from 'react';
3 |
4 | import {HandlerOf} from '../../../helpers/typeHelpers';
5 |
6 | export interface SettingsTextInputProps {
7 | placeholder?: string;
8 | className?: string;
9 | value: string;
10 | onChange: HandlerOf;
11 | isDisabled?: boolean;
12 | }
13 |
14 | const commonStyles = css`
15 | background: var(--twitter-input-bg);
16 | color: var(--settings-modal-text);
17 | border: 1px solid var(--twitter-input-border-color);
18 | display: inline-block;
19 | padding: 4px 8px;
20 | font-size: 13px;
21 | line-height: 18px;
22 | border-radius: 4px;
23 |
24 | &::placeholder {
25 | color: var(--twitter-input-placeholder);
26 | }
27 |
28 | &:focus {
29 | outline: 0;
30 | border-color: rgba(29, 161, 242, 0.8);
31 | box-shadow: inset 0 1px 3px rgba(20, 23, 26, 0.1), 0 0 8px rgba(29, 161, 242, 0.6);
32 | }
33 | `;
34 |
35 | export function SettingsTextarea(props: SettingsTextInputProps) {
36 | return (
37 |