diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml deleted file mode 100644 index a2ad3cd92a..0000000000 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ /dev/null @@ -1,57 +0,0 @@ -name: 🐞 Bug Report -description: Report a bug - -body: - - type: markdown - attributes: - value: | - ## First of all - 1. Please search for [existing issues](https://github.com/SableClient/Sable/issues?q=is%3Aissue) about this problem first. - 2. Make sure Sable is up to date. - 3. Make sure it's an issue with Sable and not something else you are using. - 4. Remember to be friendly. - - - type: textarea - id: description - attributes: - label: Describe the bug - description: A clear description of what the bug is. Include screenshots if applicable. - placeholder: Bug description - validations: - required: true - - - type: textarea - id: reproduction - attributes: - label: Reproduction - description: Steps to reproduce the behavior. - placeholder: | - 1. Go to ... - 2. Click on ... - 3. See error - - - type: textarea - id: expected-behavior - attributes: - label: Expected behavior - description: A clear description of what you expected to happen. - - - type: textarea - id: info - attributes: - label: Platform and versions - description: 'Provide OS, browser and Sable version with your Homeserver.' - placeholder: | - 1. OS: [e.g. Windows 10, MacOS] - 2. Browser: [e.g. chrome 99.5, firefox 97.2] - 3. Sable version: [e.g. 1.8.1 (app.cinny.in)] - 4. Matrix homeserver: [e.g. matrix.org] - render: shell - validations: - required: true - - - type: textarea - id: context - attributes: - label: Additional context - description: Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml deleted file mode 100644 index 0bbb982efa..0000000000 --- a/.github/ISSUE_TEMPLATE/config.yml +++ /dev/null @@ -1,4 +0,0 @@ -contact_links: - - name: đŸ’Ŧ Matrix Chat - url: https://matrix.to/#/#sable:sable.moe - about: Ask questions and talk to other Sable users and the maintainers diff --git a/.github/ISSUE_TEMPLATE/feature_request.yml b/.github/ISSUE_TEMPLATE/feature_request.yml deleted file mode 100644 index 04c1812297..0000000000 --- a/.github/ISSUE_TEMPLATE/feature_request.yml +++ /dev/null @@ -1,33 +0,0 @@ -name: 💡 Feature Request -description: Suggest an idea - -body: - - type: textarea - id: problem - attributes: - label: Describe the problem - description: A clear description of the problem this feature would solve - placeholder: "I'm always frustrated when..." - validations: - required: true - - - type: textarea - id: solution - attributes: - label: "Describe the solution you'd like" - description: A clear description of what change you would like - placeholder: 'I would like to...' - validations: - required: true - - - type: textarea - id: alternatives - attributes: - label: Alternatives considered - description: "Any alternative solutions you've considered" - - - type: textarea - id: context - attributes: - label: Additional context - description: Add any other context about the problem here. diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md deleted file mode 100644 index a866e80580..0000000000 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ /dev/null @@ -1,29 +0,0 @@ - - -### Description - - - -Fixes # - -#### Type of change - -- [ ] Bug fix (non-breaking change which fixes an issue) -- [ ] New feature (non-breaking change which adds functionality) -- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) -- [ ] This change requires a documentation update - -### Checklist: - -- [ ] My code follows the style guidelines of this project -- [ ] I have performed a self-review of my own code -- [ ] I have commented my code, particularly in hard-to-understand areas -- [ ] I have made corresponding changes to the documentation -- [ ] My changes generate no new warnings - -### AI disclosure: - -- [ ] Partially AI assisted (clarify which code was AI assisted and briefly explain what it does). -- [ ] Fully AI generated (explain what all the generated code does in moderate detail). - - diff --git a/.github/SECURITY.md b/.github/SECURITY.md deleted file mode 100644 index 9cda63bd2a..0000000000 --- a/.github/SECURITY.md +++ /dev/null @@ -1,3 +0,0 @@ -# Reporting a Vulnerability - -**If you've found a security vulnerability, please report it to security@sable.moe** diff --git a/.github/actions/prepare-tofu/action.yml b/.github/actions/prepare-tofu/action.yml deleted file mode 100644 index 0cb06882de..0000000000 --- a/.github/actions/prepare-tofu/action.yml +++ /dev/null @@ -1,62 +0,0 @@ -name: Prepare OpenTofu Deployment -description: Prepares OpenTofu in infra/web. - -inputs: - build-flavor: - description: Build flavor (stable or dev). Controls app build behavior. - required: false - default: stable - -runs: - using: composite - steps: - - name: Validate deployment configuration - shell: bash - run: | - missing=() - for name in \ - TF_HTTP_ADDRESS \ - TF_HTTP_LOCK_ADDRESS \ - TF_HTTP_UNLOCK_ADDRESS \ - TF_VAR_custom_domain \ - TF_VAR_worker_name \ - SENTRY_ORG \ - SENTRY_PROJECT - do - if [[ -z "${!name:-}" ]]; then - missing+=("$name") - fi - done - - if (( ${#missing[@]} > 0 )); then - printf 'Missing required GitHub Environment variables: %s\n' "${missing[*]}" >&2 - exit 1 - fi - - - name: Setup app and build - uses: ./.github/actions/setup - with: - build: 'true' - env: - SABLE_BUILD_FLAVOR: ${{ inputs.build-flavor }} - VITE_SENTRY_DSN: ${{ env.VITE_SENTRY_DSN }} - VITE_SENTRY_ENVIRONMENT: ${{ env.VITE_SENTRY_ENVIRONMENT }} - VITE_APP_VERSION: ${{ env.VITE_APP_VERSION }} - SENTRY_AUTH_TOKEN: ${{ env.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: ${{ env.SENTRY_ORG }} - SENTRY_PROJECT: ${{ env.SENTRY_PROJECT }} - - - name: Check formatting - shell: bash - working-directory: ${{ github.workspace }}/infra/web - run: mise run opentofu -- fmt -check - - - name: Initialize OpenTofu - shell: bash - working-directory: ${{ github.workspace }}/infra/web - run: mise run opentofu -- init -input=false -reconfigure - - - name: Validate configuration - shell: bash - working-directory: ${{ github.workspace }}/infra/web - run: mise run opentofu -- validate -no-color diff --git a/.github/actions/setup/action.yml b/.github/actions/setup/action.yml deleted file mode 100644 index 9c5c5c1b0e..0000000000 --- a/.github/actions/setup/action.yml +++ /dev/null @@ -1,75 +0,0 @@ -name: Setup App -description: Sets up Node.js, installs dependencies, and optionally builds the app. - -inputs: - install-command: - description: Command used to install dependencies. - required: false - default: pnpm install --frozen-lockfile - tauri: - description: Whether to install Tauri build dependencies via mise. - required: false - default: 'false' - build: - description: Whether to build the app after installing dependencies. - required: false - default: 'false' - build-command: - description: Command used when build is enabled. - required: false - default: pnpm run build - -runs: - using: composite - steps: - - name: Setup tools (mise) - id: setup-mise - uses: jdx/mise-action@9e7f7633ff6f6d6048a9418a68d48f288f50eb14 # v4.2.3 - with: - cache: true - - - name: Cache Rust toolchain (workaround jdx/mise-action#215) - if: ${{ inputs.tauri == 'true' }} - id: cache-rust - uses: actions/cache@55cc8345863c7cc4c66a329aec7e433d2d1c52a9 # v6.1.0 - with: - path: ~/.rustup/toolchains/ - key: rust-${{ runner.os }}-${{ hashFiles('rust-toolchain.toml') }} - restore-keys: rust-${{ runner.os }}- - - - name: Ensure task scripts are executable - shell: bash - working-directory: ${{ github.workspace }} - run: chmod -R +x scripts/ - - - name: Trust project mise configuration - shell: bash - working-directory: ${{ github.workspace }} - run: mise settings set trusted_config_paths "$GITHUB_WORKSPACE" - - - name: Install dependencies - shell: bash - working-directory: ${{ github.workspace }} - run: ${INPUTS_INSTALL_COMMAND} - env: - INPUTS_INSTALL_COMMAND: ${{ inputs.install-command }} - - - name: Install Tauri build dependencies - if: ${{ inputs.tauri == 'true' }} - shell: bash - working-directory: ${{ github.workspace }} - run: mise run tauri:setup - - - name: Force reinstall Rust on cache mismatch - if: ${{ inputs.tauri == 'true' && steps.setup-mise.outputs.cache-hit == 'true' && steps.cache-rust.outputs.cache-hit != 'true' }} - shell: bash - working-directory: ${{ github.workspace }} - run: mise install rust --force - - - name: Build app - if: ${{ inputs.build == 'true' }} - shell: bash - working-directory: ${{ github.workspace }} - run: ${INPUTS_BUILD_COMMAND} - env: - INPUTS_BUILD_COMMAND: ${{ inputs.build-command }} diff --git a/.github/dependabot.yml b/.github/dependabot.yml deleted file mode 100644 index 0d203af98c..0000000000 --- a/.github/dependabot.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Docs: - -version: 2 -updates: - - package-ecosystem: github-actions - cooldown: - default-days: 7 - directory: / - schedule: - interval: daily - open-pull-requests-limit: 5 - labels: - - internal - commit-message: - prefix: chore - groups: - github-actions: - patterns: - - '*' - - - package-ecosystem: docker - cooldown: - default-days: 7 - directory: / - schedule: - interval: daily - open-pull-requests-limit: 5 - labels: - - internal - commit-message: - prefix: chore - groups: - docker: - patterns: - - '*' - - - package-ecosystem: npm - cooldown: - default-days: 7 - directory: / - schedule: - interval: daily - open-pull-requests-limit: 10 - labels: - - internal - commit-message: - prefix: chore - groups: - npm: - patterns: - - '*' - - - package-ecosystem: cargo - cooldown: - default-days: 7 - directory: /src-tauri - schedule: - interval: daily - open-pull-requests-limit: 5 - labels: - - internal - commit-message: - prefix: chore - groups: - cargo: - patterns: - - '*' diff --git a/.github/workflows/cloudflare-web-preview.yml b/.github/workflows/cloudflare-web-preview.yml deleted file mode 100644 index 954b7056e3..0000000000 --- a/.github/workflows/cloudflare-web-preview.yml +++ /dev/null @@ -1,176 +0,0 @@ -name: Cloudflare Worker Preview Deploy - -on: - pull_request: - paths: - - 'src/**' - - 'index.html' - - 'package.json' - - 'package-lock.json' - - 'vite.config.ts' - - 'tsconfig.json' - - '.github/workflows/cloudflare-web-preview.yml' - - '.github/actions/setup/**' - push: - branches: - - dev - paths: - - 'src/**' - - 'index.html' - - 'package.json' - - 'package-lock.json' - - 'vite.config.ts' - - 'tsconfig.json' - - '.github/workflows/cloudflare-web-preview.yml' - - '.github/actions/setup/**' -concurrency: - group: cloudflare-worker-preview-${{ github.event.pull_request.number || github.ref_name }} - cancel-in-progress: true - -jobs: - deploy: - if: (github.event_name == 'pull_request' && github.event.pull_request.head.repo.full_name == github.repository && github.head_ref != 'release') || github.event_name == 'push' - runs-on: ubuntu-latest - permissions: - contents: read - pull-requests: write - steps: - - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Prepare preview metadata - id: metadata - shell: bash - run: | - preview_message="$(git log -1 --pretty=%s)" - preview_message="$(printf '%s' "$preview_message" | head -c 100)" - - { - echo 'preview_message<> "$GITHUB_OUTPUT" - - - name: Set Sentry build environment for PR preview - if: github.event_name == 'pull_request' - env: - VITE_SENTRY_DSN: ${{ secrets.VITE_SENTRY_DSN }} - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: ${{ secrets.SENTRY_ORG }} - SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} - shell: bash - run: | - echo "VITE_SENTRY_DSN=$VITE_SENTRY_DSN" >> "$GITHUB_ENV" - echo "VITE_SENTRY_ENVIRONMENT=preview" >> "$GITHUB_ENV" - echo "VITE_SENTRY_PR=${{ github.event.pull_request.number }}" >> "$GITHUB_ENV" - echo "SENTRY_AUTH_TOKEN=$SENTRY_AUTH_TOKEN" >> "$GITHUB_ENV" - echo "SENTRY_ORG=$SENTRY_ORG" >> "$GITHUB_ENV" - echo "SENTRY_PROJECT=$SENTRY_PROJECT" >> "$GITHUB_ENV" - - - name: Setup app and build - uses: ./.github/actions/setup - with: - build: 'true' - - - name: Set deploy alias - id: alias - shell: bash - run: | - if [ "${{ github.event_name }}" = "pull_request" ]; then - echo "alias=pr-${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT" - else - branch="${GITHUB_REF_NAME}" - alias="$(echo "$branch" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-\|-$//g')" - echo "alias=${alias}" >> "$GITHUB_OUTPUT" - fi - - - name: Upload Worker preview - id: deploy - uses: cloudflare/wrangler-action@ebbaa1584979971c8614a24965b4405ff95890e0 # v4.0.0 - env: - PREVIEW_MESSAGE: ${{ steps.metadata.outputs.preview_message }} - with: - apiToken: ${{ secrets.TF_CLOUDFLARE_API_TOKEN }} - accountId: ${{ secrets.TF_VAR_ACCOUNT_ID }} - command: > - versions upload - -c dist/wrangler.json - --preview-alias ${{ steps.alias.outputs.alias }} - --message "$PREVIEW_MESSAGE" - - - name: Resolve preview URL - id: preview - env: - DEPLOYMENT_URL: ${{ steps.deploy.outputs.deployment-url }} - COMMAND_OUTPUT: ${{ steps.deploy.outputs.command-output }} - ALIAS: ${{ steps.alias.outputs.alias }} - shell: bash - run: | - alias_url_pattern="^https?://${ALIAS}-[^[:space:]]+$" - preview_url="" - - if printf '%s\n' "$DEPLOYMENT_URL" | grep -Eq "$alias_url_pattern"; then - preview_url="$DEPLOYMENT_URL" - else - preview_url="$(printf '%s\n' "$COMMAND_OUTPUT" | grep -Eo "https?://${ALIAS}-[^[:space:]\"'<>)]+" | head -n 1 || true)" - fi - - if ! printf '%s\n' "$preview_url" | grep -Eq "$alias_url_pattern"; then - echo "Failed to resolve aliased Worker preview URL." >&2 - exit 1 - fi - - echo "preview_url=${preview_url}" >> "$GITHUB_OUTPUT" - - - name: Publish summary and PR comment - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - env: - MARKER: '' - PREVIEW_URL: ${{ steps.preview.outputs.preview_url }} - PREVIEW_ALIAS: ${{ steps.alias.outputs.alias }} - SHORT_SHA: ${{ github.event.pull_request.head.sha || github.sha }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const marker = process.env.MARKER; - const previewUrl = process.env.PREVIEW_URL; - const previewAlias = process.env.PREVIEW_ALIAS; - const shortSha = process.env.SHORT_SHA?.slice(0, 7); - const now = new Date().toUTCString().replace(':00 GMT', ' UTC'); - - if (!previewUrl) { - core.setFailed("Missing preview URL from Cloudflare deploy step."); - return; - } - - const tableRow = "| ✅ Deployment successful! | " + previewUrl + " | " + shortSha + " | `" + previewAlias + "` | " + now + " |"; - const comment = [ - marker, - `## Deploying with  Cloudflare Workers  Cloudflare Workers`, - ``, - `| Status | Preview URL | Commit | Alias | Updated (UTC) |`, - `| - | - | - | - | - |`, - tableRow, - ].join("\n"); - - await core.summary.addRaw(comment.replace(marker + "\n", "")).write(); - - if (context.eventName !== 'pull_request') return; - - const { owner, repo } = context.repo; - const issue_number = context.issue.number; - const comments = await github.paginate(github.rest.issues.listComments, { - owner, repo, issue_number, - }); - const existing = comments.find( - (c) => c.user.type === "Bot" && c.body.includes(marker), - ); - if (existing) { - await github.rest.issues.deleteComment({ - owner, repo, comment_id: existing.id, - }); - } - - await github.rest.issues.createComment({ owner, repo, issue_number, body: comment }); diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml deleted file mode 100644 index 9019e9916b..0000000000 --- a/.github/workflows/codeql.yml +++ /dev/null @@ -1,103 +0,0 @@ -# For most projects, this workflow file will not need changing; you simply need -# to commit it to your repository. -# -# You may wish to alter this file to override the set of languages analyzed, -# or to provide custom queries or build logic. -# -# ******** NOTE ******** -# We have attempted to detect the languages in your repository. Please check -# the `language` matrix defined below to confirm you have the correct set of -# supported CodeQL languages. -# -name: 'CodeQL Advanced' - -on: - push: - branches: ['dev'] - pull_request: - branches: ['dev'] - schedule: - - cron: '29 1 * * 2' - -jobs: - analyze: - name: Analyze (${{ matrix.language }}) - # Runner size impacts CodeQL analysis time. To learn more, please see: - # - https://gh.io/recommended-hardware-resources-for-running-codeql - # - https://gh.io/supported-runners-and-hardware-resources - # - https://gh.io/using-larger-runners (GitHub.com only) - # Consider using larger runners or machines with greater resources for possible analysis time improvements. - runs-on: ${{ (matrix.language == 'swift' && 'macos-latest') || 'ubuntu-latest' }} - permissions: - # required for all workflows - security-events: write - - # required to fetch internal or private CodeQL packs - packages: read - - # only required for workflows in private repositories - actions: read - contents: read - - strategy: - fail-fast: false - matrix: - include: - - language: actions - build-mode: none - - language: javascript-typescript - build-mode: none - # CodeQL supports the following values keywords for 'language': 'actions', 'c-cpp', 'csharp', 'go', 'java-kotlin', 'javascript-typescript', 'python', 'ruby', 'rust', 'swift' - # Use `c-cpp` to analyze code written in C, C++ or both - # Use 'java-kotlin' to analyze code written in Java, Kotlin or both - # Use 'javascript-typescript' to analyze code written in JavaScript, TypeScript or both - # To learn more about changing the languages that are analyzed or customizing the build mode for your analysis, - # see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/customizing-your-advanced-setup-for-code-scanning. - # If you are analyzing a compiled language, you can modify the 'build-mode' for that language to customize how - # your codebase is analyzed, see https://docs.github.com/en/code-security/code-scanning/creating-an-advanced-setup-for-code-scanning/codeql-code-scanning-for-compiled-languages - steps: - - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - # Add any setup steps before running the `github/codeql-action/init` action. - # This includes steps like installing compilers or runtimes (`actions/setup-node` - # or others). This is typically only required for manual builds. - # - name: Setup runtime (example) - # uses: actions/setup-example@v1 - - # Initializes the CodeQL tools for scanning. - - name: Initialize CodeQL - uses: github/codeql-action/init@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 - with: - languages: ${{ matrix.language }} - build-mode: ${{ matrix.build-mode }} - # If you wish to specify custom queries, you can do so here or in a config file. - # By default, queries listed here will override any specified in a config file. - # Prefix the list here with "+" to use these queries and those in the config file. - - # For more details on CodeQL's query packs, refer to: https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs - # queries: security-extended,security-and-quality - - # If the analyze step fails for one of the languages you are analyzing with - # "We were unable to automatically build your code", modify the matrix above - # to set the build mode to "manual" for that language. Then modify this step - # to build your code. - # â„šī¸ Command-line programs to run using the OS shell. - # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun - - name: Run manual build steps - if: matrix.build-mode == 'manual' - shell: bash - run: | - echo 'If you are using a "manual" build mode for one or more of the' \ - 'languages you are analyzing, replace this with the commands to build' \ - 'your code, for example:' - echo ' make bootstrap' - echo ' make release' - exit 1 - - - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@ff2f1c621b7f889edc0d3c761ac2e6a3f8cdb0dd # v4.37.7 - with: - category: '/language:${{matrix.language}}' diff --git a/.github/workflows/docker-publish.yml b/.github/workflows/docker-publish.yml deleted file mode 100644 index 69c3b21435..0000000000 --- a/.github/workflows/docker-publish.yml +++ /dev/null @@ -1,117 +0,0 @@ -name: Build and publish Docker image - -on: - push: - branches: [dev] - tags: - - 'v*' - pull_request: - paths: - - 'Dockerfile' - - '.github/workflows/docker-publish.yml' - workflow_dispatch: - inputs: - git_tag: - description: 'Git tag to build and publish (e.g. v1.2.3). Leave empty to build current HEAD as a dev image.' - required: false - type: string - -env: - REGISTRY: ghcr.io - IMAGE_NAME: ${{ github.repository }} - -jobs: - build-and-push: - runs-on: ubuntu-latest - permissions: - contents: read - packages: write - attestations: write - artifact-metadata: write - id-token: write - - steps: - - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Log in to GitHub Container Registry - if: github.event_name != 'pull_request' - uses: docker/login-action@dbcb813823bdd20940b903addbd779551569679f # v4.6.0 - with: - registry: ${{ env.REGISTRY }} - username: ${{ github.actor }} - password: ${{ secrets.GITHUB_TOKEN }} - - - uses: ./.github/actions/resolve-release-meta - id: release_meta - with: - input-tag: ${{ inputs.git_tag }} - - - name: Checkout release target - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - ref: ${{ steps.release_meta.outputs.ref }} - - - name: Extract metadata - id: meta - uses: docker/metadata-action@dc802804100637a589fabce1cb79ff13a1411302 # v6.2.0 - with: - images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - flavor: | - latest=false - tags: | - # dev branch or manual dispatch without a tag: short commit SHA + dev - type=sha,prefix=,format=short,enable=${{ steps.release_meta.outputs.version != '' && steps.release_meta.outputs.nightly == 'true' }} - type=raw,value=dev,enable=${{ steps.release_meta.outputs.version != '' && steps.release_meta.outputs.nightly == 'true' }} - - # git tags (push or manual dispatch with a tag): semver breakdown + latest - type=raw,value=latest,enable=${{ steps.release_meta.outputs.version != '' && steps.release_meta.outputs.nightly != 'true' }} - type=semver,pattern={{version}},value=${{ steps.release_meta.outputs.version }},enable=${{ steps.release_meta.outputs.version != '' && steps.release_meta.outputs.nightly != 'true' }} - type=semver,pattern={{major}}.{{minor}},value=${{ steps.release_meta.outputs.version }},enable=${{ steps.release_meta.outputs.version != '' && steps.release_meta.outputs.nightly != 'true' }} - type=semver,pattern={{major}},value=${{ steps.release_meta.outputs.version }},enable=${{ steps.release_meta.outputs.version != '' && steps.release_meta.outputs.nightly != 'true' && !startsWith(steps.release_meta.outputs.version, 'v0.') }} - - - name: Compute short SHA - id: vars - run: echo "short_sha=$(git rev-parse --short HEAD)" >> $GITHUB_OUTPUT - - - name: Setup app - uses: ./.github/actions/setup - - - name: Build site - env: - VITE_BUILD_HASH: ${{ steps.vars.outputs.short_sha }} - VITE_APP_VERSION: ${{ steps.release_meta.outputs.version }} - SABLE_BUILD_FLAVOR: ${{ steps.release_meta.outputs.build_flavor }} - run: | - NODE_OPTIONS=--max_old_space_size=4096 pnpm run build - - - name: Set up QEMU - uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0 - - - name: Set up Docker Buildx - uses: docker/setup-buildx-action@bb05f3f5519dd87d3ba754cc423b652a5edd6d2c # v4.2.0 - - - name: Build and push Docker image - id: push - uses: docker/build-push-action@53b7df96c91f9c12dcc8a07bcb9ccacbed38856a # v7.3.0 - with: - context: . - push: ${{ github.event_name != 'pull_request' }} - platforms: linux/amd64,linux/arm64 - tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} - cache-from: type=gha - cache-to: type=gha,mode=max - build-contexts: | - site-dist=./dist - - - name: Generate artifact attestation - if: github.event_name != 'pull_request' - uses: actions/attest-build-provenance@4d101475d8b20a2381f78447822ac1eab6504dd8 # v4.2.2 - with: - subject-name: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} - subject-digest: ${{ steps.push.outputs.digest }} - push-to-registry: true diff --git a/.github/workflows/flake-lock-fix.yml b/.github/workflows/flake-lock-fix.yml deleted file mode 100644 index 0e527602de..0000000000 --- a/.github/workflows/flake-lock-fix.yml +++ /dev/null @@ -1,71 +0,0 @@ -name: Fix flake hashes - -on: - workflow_dispatch: - push: - branches: [dev] - paths: ['pnpm-lock.yaml'] - -jobs: - fix: - name: Fix flake hashes - runs-on: ubuntu-latest - permissions: - id-token: write - contents: write - steps: - - name: Generate bot token - id: app-token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - with: - app-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - permission-contents: write - - - name: Checkout dev - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - ref: dev - persist-credentials: true - token: ${{ steps.app-token.outputs.token }} - - - name: Install Determinate Nix - uses: DeterminateSystems/determinate-nix-action@61cbfe2efc2d4e7a8a6d56967c3c1058e846c858 # v3.21.9 - - - id: check - run: nix flake check -L --keep-going - continue-on-error: true - - - name: Fix hash mismatches - if: steps.check.outcome == 'failure' - run: determinate-nixd fix hashes --auto-apply - - - name: Get GitHub App User ID - id: get-user-id - run: echo "user-id=$(gh api "/users/${STEPS_APP_TOKEN_OUTPUTS_APP_SLUG}[bot]" --jq .id)" >> "$GITHUB_OUTPUT" - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - STEPS_APP_TOKEN_OUTPUTS_APP_SLUG: ${{ steps.app-token.outputs.app-slug }} - - - name: Configure bot git identity - run: | - git config --global user.name "${STEPS_APP_TOKEN_OUTPUTS_APP_SLUG}[bot]" - git config --global user.email "${STEPS_GET_USER_ID_OUTPUTS_USER_ID}+${STEPS_APP_TOKEN_OUTPUTS_APP_SLUG}[bot]@users.noreply.github.com" - gh auth setup-git - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - STEPS_APP_TOKEN_OUTPUTS_APP_SLUG: ${{ steps.app-token.outputs.app-slug }} - STEPS_GET_USER_ID_OUTPUTS_USER_ID: ${{ steps.get-user-id.outputs.user-id }} - - - name: Commit and push if changed - if: steps.check.outcome == 'failure' - shell: bash - run: | - set -euo pipefail - if git diff --quiet; then - echo "No changes after fix hashes; nothing to commit." - exit 0 - fi - git add --update --ignore-removal . - git commit -m "chore(nix): auto-fix nix hashes" - git push origin HEAD:dev --force-with-lease diff --git a/.github/workflows/prepare-release.yml b/.github/workflows/prepare-release.yml deleted file mode 100644 index 29430ba8b6..0000000000 --- a/.github/workflows/prepare-release.yml +++ /dev/null @@ -1,49 +0,0 @@ -name: Create Release PR - -on: - push: - branches: [dev] - -permissions: {} - -jobs: - prepare-release: - if: "!contains(github.event.head_commit.message, 'chore: prepare release')" - runs-on: ubuntu-latest - permissions: - contents: write - pull-requests: write - steps: - - name: Generate bot token - id: generate-token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - with: - app-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - permission-contents: write - permission-pull-requests: write - - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - fetch-depth: 0 - persist-credentials: true - token: ${{ steps.generate-token.outputs.token }} - - - name: Setup app - uses: ./.github/actions/setup - with: - install-command: '' - - - uses: fregante/setup-git-user@024bc0b8e177d7e77203b48dab6fb45666854b35 # v2.0.2 - - - name: Prepare Release - run: mise run knope -- prepare-release --verbose - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} - - - name: Add internal label - run: | - PR_NUMBER=$(gh pr list --head release --json number --jq '.[0].number') - gh pr edit "$PR_NUMBER" --add-label internal - env: - GH_TOKEN: ${{ steps.generate-token.outputs.token }} diff --git a/.github/workflows/quality-checks.yml b/.github/workflows/quality-checks.yml deleted file mode 100644 index b192f2a173..0000000000 --- a/.github/workflows/quality-checks.yml +++ /dev/null @@ -1,115 +0,0 @@ -name: Quality checks - -on: - pull_request: - push: - branches: [dev] - merge_group: - -jobs: - format: - name: Format check - runs-on: ubuntu-latest - if: github.head_ref != 'release' - permissions: - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Setup app - uses: ./.github/actions/setup - - - name: Check formatting - run: pnpm run fmt:check - - lint: - name: Lint - runs-on: ubuntu-latest - if: github.head_ref != 'release' - permissions: - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Setup app - uses: ./.github/actions/setup - - - name: Run Lint - run: pnpm run lint - - typecheck: - name: Typecheck - runs-on: ubuntu-latest - if: github.head_ref != 'release' - permissions: - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Setup app - uses: ./.github/actions/setup - - - name: Run TypeScript typecheck - run: pnpm run typecheck --pretty false - - knip: - name: Knip - runs-on: ubuntu-latest - if: github.head_ref != 'release' - permissions: - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Setup app - uses: ./.github/actions/setup - - - name: Run Knip - run: pnpm run knip - - tests: - name: Tests - runs-on: ubuntu-latest - if: github.head_ref != 'release' - permissions: - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Setup app - uses: ./.github/actions/setup - - - name: Run tests - run: pnpm run test:run - - build: - name: Build - runs-on: ubuntu-latest - if: github.head_ref != 'release' - permissions: - contents: read - steps: - - name: Checkout repository - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - persist-credentials: false - - - name: Setup app and build - uses: ./.github/actions/setup - with: - build: 'true' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index f0b4cab6e5..0000000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,39 +0,0 @@ -name: Release - -on: - pull_request: - types: [closed] - branches: [dev] - -permissions: {} - -jobs: - release: - if: github.head_ref == 'release' && github.event.pull_request.merged == true - runs-on: ubuntu-latest - permissions: - contents: write - steps: - - name: Generate bot token - id: generate-token - uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - with: - app-id: ${{ secrets.APP_ID }} - private-key: ${{ secrets.APP_PRIVATE_KEY }} - permission-contents: write - - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - with: - fetch-depth: 0 - persist-credentials: true - token: ${{ steps.generate-token.outputs.token }} - - - name: Setup app - uses: ./.github/actions/setup - with: - install-command: '' - - - name: Create Release - run: mise run knope -- release --verbose - env: - GITHUB_TOKEN: ${{ steps.generate-token.outputs.token }} diff --git a/.github/workflows/require-changeset.yml b/.github/workflows/require-changeset.yml deleted file mode 100644 index 06ef3b17be..0000000000 --- a/.github/workflows/require-changeset.yml +++ /dev/null @@ -1,114 +0,0 @@ -name: Require Changeset - -on: - pull_request: - types: [opened, synchronize, reopened, labeled, unlabeled] - merge_group: - branches: [dev] - -permissions: {} - -jobs: - require-changeset: - runs-on: ubuntu-latest - if: github.head_ref != 'release' && github.event_name != 'merge_group' - permissions: - contents: read - pull-requests: write - steps: - - name: Check for internal label - id: labels - shell: bash - env: - LABELS: ${{ toJSON(github.event.pull_request.labels.*.name) }} - run: | - if echo "$LABELS" | grep -q '"internal"'; then - echo "skip=true" >> "$GITHUB_OUTPUT" - else - echo "skip=false" >> "$GITHUB_OUTPUT" - fi - - - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - if: steps.labels.outputs.skip == 'false' - with: - fetch-depth: 0 - persist-credentials: false - - - name: Check for changeset added by this PR - if: steps.labels.outputs.skip == 'false' - id: check - shell: bash - env: - BASE_REF: ${{ github.event.pull_request.base.ref }} - run: | - # Only count changeset files this PR added, ignoring pre-existing ones on the base branch. - count=$(git diff --name-only --diff-filter=A "origin/${BASE_REF}...HEAD" | grep -E '^\.changeset/.+\.md$' | grep -cv README.md || true) - if [[ "$count" -eq 0 ]]; then - echo "found=false" >> "$GITHUB_OUTPUT" - else - echo "found=true" >> "$GITHUB_OUTPUT" - echo "Found $count new changeset file(s)." - fi - - - name: Manage changeset comment - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - env: - SKIP: ${{ steps.labels.outputs.skip }} - CHANGESET_FOUND: ${{ steps.check.outputs.found }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const marker = ''; - const skip = process.env.SKIP === 'true'; - const found = process.env.CHANGESET_FOUND === 'true'; - const { owner, repo } = context.repo; - const issue_number = context.issue.number; - - const comments = await github.paginate(github.rest.issues.listComments, { - owner, repo, issue_number, - }); - const existing = comments.find( - (c) => c.user.type === 'Bot' && c.body.includes(marker), - ); - - if (skip || found) { - // Clean up the warning comment — changeset added or PR marked internal - if (existing) { - await github.rest.issues.deleteComment({ - owner, repo, comment_id: existing.id, - }); - } - return; - } - - const body = `${marker} - ## âš ī¸ Missing changeset - - This pull request does not include a changeset. Please add one before requesting review so the change is properly documented and included in the release notes. - - **How to add a changeset:** - - 1. Run \`pnpm run document-change\` (interactive) and commit the generated file, or - 2. Manually create \`.changeset/.md\`: - - \`\`\`md - --- - default: patch - --- - - Short user-facing summary of the change. - \`\`\` - - Replace \`patch\` with \`major\`, \`minor\`, \`patch\`, \`docs\`, or \`note\` as appropriate. - - 📖 Read more in [CONTRIBUTING.md](https://github.com/SableClient/Sable/blob/dev/CONTRIBUTING.md#release-notes-and-versioning-knope). - - > If this PR is internal/maintenance with no user-facing impact, a maintainer can add the \`internal\` label to skip this check.`; - - if (existing) { - await github.rest.issues.deleteComment({ - owner, repo, comment_id: existing.id, - }); - } - await github.rest.issues.createComment({ owner, repo, issue_number, body }); - core.setFailed('No changeset found. Add a changeset file or apply the "internal" label to skip.'); diff --git a/.github/workflows/sentry-preview-issues.yml b/.github/workflows/sentry-preview-issues.yml deleted file mode 100644 index 8020ee7ffd..0000000000 --- a/.github/workflows/sentry-preview-issues.yml +++ /dev/null @@ -1,231 +0,0 @@ -name: Sentry Preview Error Triage - -on: - pull_request: - types: [opened, synchronize, reopened] - paths: - - 'src/**' - - 'index.html' - - 'package.json' - - 'vite.config.ts' - - 'tsconfig.json' - workflow_dispatch: - inputs: - pr_number: - description: 'PR number to triage' - required: true - type: number - -jobs: - triage: - # Only run for PRs from the same repo (not forks) or manual dispatch - if: > - (github.event_name == 'pull_request' && - github.event.pull_request.head.repo.full_name == github.repository) || - github.event_name == 'workflow_dispatch' - runs-on: ubuntu-latest - permissions: - issues: write - pull-requests: write - steps: - - name: Triage Sentry preview errors - uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - env: - SENTRY_AUTH_TOKEN: ${{ secrets.SENTRY_AUTH_TOKEN }} - SENTRY_ORG: ${{ secrets.SENTRY_ORG }} - SENTRY_PROJECT: ${{ secrets.SENTRY_PROJECT }} - PR_NUMBER: ${{ github.event.pull_request.number || github.event.inputs.pr_number }} - with: - github-token: ${{ secrets.GITHUB_TOKEN }} - script: | - const sentryToken = process.env.SENTRY_AUTH_TOKEN; - const sentryOrg = process.env.SENTRY_ORG; - const sentryProject = process.env.SENTRY_PROJECT; - const prNumber = Number(process.env.PR_NUMBER); - - if (!prNumber) { - core.info('No PR number available — skipping triage.'); - return; - } - if (!sentryToken || !sentryOrg || !sentryProject) { - core.warning('Sentry credentials not configured — skipping triage.'); - return; - } - - const COMMENT_MARKER = ''; - const { owner, repo } = context.repo; - - // Create a label if it doesn't already exist - async function ensureLabel(name, description, color) { - try { - await github.rest.issues.getLabel({ owner, repo, name }); - } catch { - try { - await github.rest.issues.createLabel({ owner, repo, name, description, color }); - } catch (err) { - core.warning(`Could not create label "${name}": ${err.message}`); - } - } - } - - // Find an existing GitHub issue that tracks a given Sentry issue ID - async function findExistingGhIssue(sentryIssueId) { - const marker = `sentry-id:${sentryIssueId}`; - const result = await github.rest.search.issuesAndPullRequests({ - q: `repo:${owner}/${repo} is:issue label:sentry-preview "${marker}" in:body`, - }); - return result.data.total_count > 0 ? result.data.items[0] : null; - } - - // Create or update the sticky PR comment with the triage summary table - async function upsertPrComment(rows) { - const now = new Date().toUTCString().replace(':00 GMT', ' UTC'); - let body; - - if (rows.length === 0) { - body = [ - COMMENT_MARKER, - '## Sentry Preview Error Triage', - '', - `No Sentry errors found for this PR's preview deployment as of ${now}.`, - '', - '_This comment updates automatically after each push._', - ].join('\n'); - } else { - const tableRows = rows.map( - (r) => - `| [${r.title.slice(0, 70)}](${r.permalink}) | ${r.count} | ${new Date(r.firstSeen).toLocaleDateString()} | #${r.ghIssueNumber} |` - ); - body = [ - COMMENT_MARKER, - '## Sentry Preview Error Triage', - '', - `**${rows.length} error type(s)** detected in this PR's preview deployment:`, - '', - '| Error | Events | First seen | Issue |', - '| ----- | ------ | ---------- | ----- |', - ...tableRows, - '', - `_Last checked: ${now}. Exclude these from your issues view with \`-label:sentry-preview\`._`, - ].join('\n'); - } - - const comments = await github.paginate(github.rest.issues.listComments, { - owner, - repo, - issue_number: prNumber, - }); - const existing = comments.find( - (c) => c.user.type === 'Bot' && c.body.includes(COMMENT_MARKER) - ); - - if (existing) { - await github.rest.issues.updateComment({ - owner, - repo, - comment_id: existing.id, - body, - }); - } else { - await github.rest.issues.createComment({ - owner, - repo, - issue_number: prNumber, - body, - }); - } - } - - // Query Sentry for unresolved issues tagged with this PR number in the preview env - const query = encodeURIComponent(`is:unresolved pr:${prNumber}`); - const sentryUrl = - `https://sentry.io/api/0/projects/${sentryOrg}/${sentryProject}/issues/` + - `?query=${query}&environment=preview&limit=100`; - - let sentryIssues; - try { - const resp = await fetch(sentryUrl, { - headers: { Authorization: `Bearer ${sentryToken}` }, - }); - if (!resp.ok) { - const msg = await resp.text(); - core.warning(`Sentry API returned ${resp.status}: ${msg.slice(0, 200)}`); - return; - } - sentryIssues = await resp.json(); - } catch (err) { - core.warning(`Sentry API unreachable: ${err.message}`); - return; - } - - if (!Array.isArray(sentryIssues) || sentryIssues.length === 0) { - await upsertPrComment([]); - return; - } - - // Ensure the shared and PR-specific labels exist - await ensureLabel('sentry-preview', 'Automated Sentry preview error', 'e4e669'); - await ensureLabel(`pr-${prNumber}`, `Preview errors from PR #${prNumber}`, 'fbca04'); - - const rows = []; - for (const issue of sentryIssues) { - const { - id: sentryId, - title, - culprit, - permalink, - count, - userCount, - firstSeen, - lastSeen, - } = issue; - const displayTitle = (title || culprit || 'Unknown error').trim(); - const sentryMarker = `sentry-id:${sentryId}`; - - const existing = await findExistingGhIssue(sentryId); - let ghIssueNumber; - - if (existing) { - ghIssueNumber = existing.number; - // Reopen if it was closed (e.g. after a previous fix that regressed) - if (existing.state === 'closed') { - await github.rest.issues.update({ - owner, - repo, - issue_number: ghIssueNumber, - state: 'open', - }); - core.info(`Reopened GH issue #${ghIssueNumber} for Sentry issue ${sentryId}`); - } - } else { - const issueBody = [ - ``, - `## Sentry Error — PR #${prNumber} Preview`, - '', - `**Error:** [${displayTitle}](${permalink})`, - `**First seen:** ${new Date(firstSeen).toUTCString()}`, - `**Last seen:** ${new Date(lastSeen).toUTCString()}`, - `**Events:** ${count} | **Affected users:** ${userCount}`, - '', - `This issue was automatically created from a Sentry error detected in the preview deployment for PR #${prNumber}.`, - '', - '> [!NOTE]', - '> To exclude automated preview issues from your issues view, filter with: `-label:sentry-preview`', - ].join('\n'); - - const created = await github.rest.issues.create({ - owner, - repo, - title: `[Sentry] ${displayTitle.slice(0, 120)}`, - body: issueBody, - labels: ['sentry-preview', `pr-${prNumber}`], - }); - ghIssueNumber = created.data.number; - core.info(`Created GH issue #${ghIssueNumber} for Sentry issue ${sentryId}`); - } - - rows.push({ title: displayTitle, permalink, count, firstSeen, ghIssueNumber }); - } - - await upsertPrComment(rows); - core.info(`Triage complete: ${rows.length} Sentry issue(s) processed for PR #${prNumber}.`); diff --git a/README.md b/README.md index edf105f554..f7a6a1b1fe 100644 --- a/README.md +++ b/README.md @@ -1,148 +1,17 @@ -# Sable +# Mable -A Matrix client built to enhance the user experience with quality-of-life features, cosmetics, utilities, and sheer usability. See the [changelog](https://github.com/SableClient/Sable/blob/dev/CHANGELOG.md). +A Matrix client built to enhance the user experience with quality-of-life features, cosmetics, utilities, and sheer usability. See the [changelog](https://github.com/Merconix/Mable/blob/dev/CHANGELOG.md). -Soon to be replaced desktop apps can be downloaded [here](https://github.com/7w1/sable/releases/tag/1.0.0). They auto-update by pulling the website. - -Join our matrix space [here](https://matrix.to/#/#sable:sable.moe) to discuss features, issues, or meowing. - -Forked from [Cinny](https://github.com/cinnyapp/cinny/). +This fork is a customised version of the [Sable project](https://github.com/sablecient/sable) to stay on more stable builds for longer and apply personalized tweaks, mostly style related. +Sable is originally forked from the more stable but less feature-packed [Cinny](https://github.com/cinnyapp/cinny/), so feel free to check either out as they might better suit your needs. ## Getting started -The stable web app is available at [app.sable.moe](https://app.sable.moe/) and tracks the [latest GitHub release](https://github.com/SableClient/Sable/releases/latest). Nightly builds are available at [dev.sable.moe](https://dev.sable.moe/) and from the [`nightly` GitHub release](https://github.com/SableClient/Sable/releases/tag/nightly). - -You can also download our desktop app for Windows and Linux from [releases](https://github.com/SableClient/Sable/releases/latest). Release artifacts include build attestations. AppImage and Windows installations update automatically; `.deb`, `.rpm`, and AUR installations update through their package manager. - -### Desktop (Linux / macOS / Windows) - -Download -  -Flathub - -On macOS, via our [Homebrew tap](https://github.com/SableClient/homebrew-sable): - -```sh -brew install --cask SableClient/sable/sable -``` - -The fully qualified name matters: since [Homebrew 6.0.0](https://brew.sh/2026/06/11/homebrew-6.0.0/) non-official taps need explicit trust, and installing this way trusts just this one cask. `brew tap` followed by a short-name install now fails unless you also run `brew trust`. - -On Linux, nightly builds have their own Flatpak remote, rebuilt from `dev` every night: - -```sh -flatpak remote-add --if-not-exists sable-nightly https://sableclient.github.io/Sable/sable-nightly.flatpakrepo -flatpak install sable-nightly moe.sable.client.Nightly -``` - -It installs alongside the stable Flathub build under a separate application ID. Built by the `build-nightly-flatpak` and `publish-nightly-flatpak` jobs in [`tauri-build.yml`](.github/workflows/tauri-build.yml). - -## Android (Obtainium) - -Android APKs are published to every release, and [Obtainium](https://obtainium.imranr.dev) keeps them updated straight from GitHub. Each release also ships an `obtainium.json` app config. Use it for the nightly channel, where prereleases and date-based version tracking have to be enabled to follow the rolling `nightly` tag. - -### Stable - -Add to Obtainium -  -App config -  -Download APK - -### Nightly - -Add to Obtainium -  -App config -  -Download APK - -### Setup & install - -1. Install [Obtainium](https://github.com/ImranR98/Obtainium/releases/latest). -2. Tap **Add to Obtainium** above. Stable opens the **Add App** page prefilled with `https://github.com/SableClient/Sable`; nightly opens an import prompt, since it carries the prerelease and version-tracking settings the rolling `nightly` tag needs. -3. Or download the `obtainium.json` for either channel and import it with **Import/Export → Import from file**. - -Android builds are produced by the `android` job in [`tauri-build.yml`](.github/workflows/tauri-build.yml), and the config by the `obtainium` job in the same workflow. - -### Relevant variables and switching between Nightly and Stable - -Relevant variable differences between Nightly and Stable: -- *Include prereleases* - `true` for Nightly, `false` for Stable -- *Fallback to older releases* - `false` for Nightly, `true` for Stable -- *Use latest asset upload as release date* - `true` for Nightly, `false` for Stable (this is due to Nightly builds being uploaded to one release instead of creating new ones) -- *Use release date as version string (pseudo-version)* - `true` for Nightly, `false` for Stable (this is due to Nightly builds being uploaded to one release instead of creating new ones) - -## iOS (AltStore / SideStore) +The web app is available [here](https://merconix.com/mable) and gets updated whenever future releases have new features I'm interested in and are deemed stable. -Sable iOS builds are distributed as unsigned IPAs through [AltStore](https://altstore.io) and [SideStore](https://sidestore.io). Each release publishes both the IPA and an `altstore-source.json` manifest — stable builds to the [latest GitHub release](https://github.com/SableClient/Sable/releases/latest), nightly builds to the [`nightly` GitHub release](https://github.com/SableClient/Sable/releases/tag/nightly). - -### Stable Source - -Add to AltStore -  -Add to SideStore -  -Direct URL - -### Nightly Source - -Add to AltStore -  -Add to SideStore -  -Direct URL - -### Setup & install - -1. Set up [AltStore Classic](https://faq.altstore.io/altstore-classic/altserver) or [SideStore](https://docs.sidestore.io) on your device. -2. Add the Sable source (tap a button above), or add it manually: - - AltStore (stable): `altstore://source?url=https://github.com/SableClient/Sable/releases/latest/download/altstore-source.json` - - SideStore (stable): `sidestore://source?url=https://github.com/SableClient/Sable/releases/latest/download/altstore-source.json` - - AltStore (nightly): `altstore://source?url=https://github.com/SableClient/Sable/releases/download/nightly/altstore-source.json` - - SideStore (nightly): `sidestore://source?url=https://github.com/SableClient/Sable/releases/download/nightly/altstore-source.json` -3. Install Sable from the source. The IPA is unsigned; AltStore/SideStore re-sign it with your personal development certificate at install time, so apps refresh every 7 days (the standard free-account limitation). - -iOS builds are produced by the `ios` job in [`tauri-build.yml`](.github/workflows/tauri-build.yml) and track the same `dev`/`v*` triggers as desktop builds. +Electron-based desktop apps can be downloaded [here](https://github.com/Merconix/Mable-Electron/releases). They auto-update by pulling the website. ## Self-hosting -You have a few options for self hosting, you can: -1. Run the prebuilt docker container. -2. Deploy on a site like GitLab Pages. Jae has a [guide here](https://docs.j4.lc/Tutorials/Deploying-Sable-on-GitLab-Pages). -3. Build it yourself. - -### Docker - -Prebuilt images are published to `ghcr.io/sableclient/sable`. - -- `latest` tracks the current latest version release. -- `dev` tracks the current `dev` branch image. -- `X.Y.Z` tags are versioned releases. -- `X.Y` tags float within a release line. -- Pushes to `dev` also publish a short commit SHA tag. - -Run the latest image with: - -```sh -docker run --rm -p 8080:8080 ghcr.io/sableclient/sable:latest -``` - -Then open `http://localhost:8080`. - -If you want to override the bundled [`config.json`](config.json), mount your own -file at `/app/config.json`: - -```yaml -services: - sable: - image: ghcr.io/sableclient/sable:latest - ports: - - '8080:8080' - volumes: - - ./config.json:/app/config.json:ro -``` - -### Build it yourself - +These steps are primarily here for my own reference, but you can follow them to host your own instance if you really want: To build and serve Sable yourself with nginx, clone this repo and build it: ```sh @@ -154,6 +23,16 @@ After that, you can copy the dist/ directory to your server and serve it. * In the [`config.json`](config.json), you can modify the default homeservers, feature rooms/spaces, toggle the account switcher, and toggle experimental simplified slilding sync support. +* To deploy on subdirectory, you need to rebuild the app youself after updating the `base` path in [`build.config.ts`](build.config.ts). + * For example, if you want to deploy on `https://sable.moe/app`, then set `base: '/app'`. + * This is set to default to /mable in this branch +* Running on a subdirectory using Apache has given me some problems with refreshing the page leading to 404 errors, whilst not a total fix, the following rewrite rules have fixed the majority of those problems by redirecting back to the root url +``` +RewriteEngine On +RewriteRule (mable/)(.+).com$ "/mable" [R] +RewriteRule (mable/home/)$ "/mable" [R] +````` + #### Optional default client settings While the default settings are recommended for most users, you can optionally add a top-level `"settingsDefaults"` object whose keys match [client settings](src/app/state/settings.ts) (only fields you want to override) to override them. The default settings for any new logins will match these. Existing keys in local storage or users who chose to sync settings with their account data will still have their settings set. @@ -176,9 +55,6 @@ For example: Invalid or unknown keys are ignored. -* To deploy on subdirectory, you need to rebuild the app youself after updating the `base` path in [`build.config.ts`](build.config.ts). - * For example, if you want to deploy on `https://sable.moe/app`, then set `base: '/app'`. - ## Local development > [!TIP] diff --git a/build.config.ts b/build.config.ts index ec8a41d087..443e06a541 100644 --- a/build.config.ts +++ b/build.config.ts @@ -1,3 +1,3 @@ export default { - base: '/', + base: '/mable', }; diff --git a/config.json b/config.json index feac16efda..1328a733b0 100644 --- a/config.json +++ b/config.json @@ -1,7 +1,7 @@ { "productName": "Sable", "defaultHomeserver": 0, - "homeserverList": ["matrix.org", "mozilla.org", "unredacted.org", "sable.moe", "kendama.moe"], + "homeserverList": ["matrix.merconix.com", "matrix.org", "mozilla.org", "unredacted.org", "sable.moe", "kendama.moe"], "allowCustomHomeservers": true, "elementCallUrl": null, @@ -42,7 +42,7 @@ "hashRouter": { "enabled": false, - "basename": "/" + "basename": "/mable" }, "gifs": { diff --git a/index.html b/index.html index 69d8235a94..77497ef64b 100644 --- a/index.html +++ b/index.html @@ -3,13 +3,10 @@ - - Sable Client - - + + Mable Client + + - - + + - - + + diff --git a/public/favicon.png b/public/favicon.png index 4638bcb333..c9dc1f0eea 100644 Binary files a/public/favicon.png and b/public/favicon.png differ diff --git a/public/font/AdwaitaMono-Regular.ttf b/public/font/AdwaitaMono-Regular.ttf new file mode 100644 index 0000000000..7f95a6771b Binary files /dev/null and b/public/font/AdwaitaMono-Regular.ttf differ diff --git a/public/font/AdwaitaSans-Regular.ttf b/public/font/AdwaitaSans-Regular.ttf new file mode 100644 index 0000000000..6fcafd9b0b Binary files /dev/null and b/public/font/AdwaitaSans-Regular.ttf differ diff --git a/public/full_res_sable.png b/public/full_res_sable.png index cb7d599e3e..f1c2dbd8c5 100644 Binary files a/public/full_res_sable.png and b/public/full_res_sable.png differ diff --git a/public/highlight.svg b/public/highlight.svg new file mode 100644 index 0000000000..0ad405f742 --- /dev/null +++ b/public/highlight.svg @@ -0,0 +1,69 @@ + + diff --git a/public/logo-maskable.svg b/public/logo-maskable.svg new file mode 100644 index 0000000000..a57b179285 --- /dev/null +++ b/public/logo-maskable.svg @@ -0,0 +1,52 @@ + + diff --git a/public/logo.svg b/public/logo.svg new file mode 100644 index 0000000000..b31ca21829 --- /dev/null +++ b/public/logo.svg @@ -0,0 +1,92 @@ + + diff --git a/public/res/logo-maskable/logo-maskable-114x114.png b/public/res/logo-maskable/logo-maskable-114x114.png index def2336ae7..2a0fc1ae6d 100644 Binary files a/public/res/logo-maskable/logo-maskable-114x114.png and b/public/res/logo-maskable/logo-maskable-114x114.png differ diff --git a/public/res/logo-maskable/logo-maskable-120x120.png b/public/res/logo-maskable/logo-maskable-120x120.png index 78e01535f3..5f84b2c434 100644 Binary files a/public/res/logo-maskable/logo-maskable-120x120.png and b/public/res/logo-maskable/logo-maskable-120x120.png differ diff --git a/public/res/logo-maskable/logo-maskable-144x144.png b/public/res/logo-maskable/logo-maskable-144x144.png index d3cf3a09d5..8281defb94 100644 Binary files a/public/res/logo-maskable/logo-maskable-144x144.png and b/public/res/logo-maskable/logo-maskable-144x144.png differ diff --git a/public/res/logo-maskable/logo-maskable-152x152.png b/public/res/logo-maskable/logo-maskable-152x152.png index f3e493de2d..bbd0b98695 100644 Binary files a/public/res/logo-maskable/logo-maskable-152x152.png and b/public/res/logo-maskable/logo-maskable-152x152.png differ diff --git a/public/res/logo-maskable/logo-maskable-167x167.png b/public/res/logo-maskable/logo-maskable-167x167.png index 1bfa60cce7..fab53efb86 100644 Binary files a/public/res/logo-maskable/logo-maskable-167x167.png and b/public/res/logo-maskable/logo-maskable-167x167.png differ diff --git a/public/res/logo-maskable/logo-maskable-180x180.png b/public/res/logo-maskable/logo-maskable-180x180.png index 86c707283f..318f7edce2 100644 Binary files a/public/res/logo-maskable/logo-maskable-180x180.png and b/public/res/logo-maskable/logo-maskable-180x180.png differ diff --git a/public/res/logo-maskable/logo-maskable-192x192.png b/public/res/logo-maskable/logo-maskable-192x192.png index 5c06f3a741..69d8bc659c 100644 Binary files a/public/res/logo-maskable/logo-maskable-192x192.png and b/public/res/logo-maskable/logo-maskable-192x192.png differ diff --git a/public/res/logo-maskable/logo-maskable-256x256.png b/public/res/logo-maskable/logo-maskable-256x256.png index 4fd058b09a..148bd77578 100644 Binary files a/public/res/logo-maskable/logo-maskable-256x256.png and b/public/res/logo-maskable/logo-maskable-256x256.png differ diff --git a/public/res/logo-maskable/logo-maskable-36x36.png b/public/res/logo-maskable/logo-maskable-36x36.png index 88115eaef7..e5f0752a5e 100644 Binary files a/public/res/logo-maskable/logo-maskable-36x36.png and b/public/res/logo-maskable/logo-maskable-36x36.png differ diff --git a/public/res/logo-maskable/logo-maskable-384x384.png b/public/res/logo-maskable/logo-maskable-384x384.png index 73d09b9225..bc773e1d26 100644 Binary files a/public/res/logo-maskable/logo-maskable-384x384.png and b/public/res/logo-maskable/logo-maskable-384x384.png differ diff --git a/public/res/logo-maskable/logo-maskable-48x48.png b/public/res/logo-maskable/logo-maskable-48x48.png index 389d4d402a..a112c4b098 100644 Binary files a/public/res/logo-maskable/logo-maskable-48x48.png and b/public/res/logo-maskable/logo-maskable-48x48.png differ diff --git a/public/res/logo-maskable/logo-maskable-512x512.png b/public/res/logo-maskable/logo-maskable-512x512.png index 30b58a211f..d5d95dce0a 100644 Binary files a/public/res/logo-maskable/logo-maskable-512x512.png and b/public/res/logo-maskable/logo-maskable-512x512.png differ diff --git a/public/res/logo-maskable/logo-maskable-57x57.png b/public/res/logo-maskable/logo-maskable-57x57.png index 699ef9324a..adf6a0b2c3 100644 Binary files a/public/res/logo-maskable/logo-maskable-57x57.png and b/public/res/logo-maskable/logo-maskable-57x57.png differ diff --git a/public/res/logo-maskable/logo-maskable-60x60.png b/public/res/logo-maskable/logo-maskable-60x60.png index 92f2f74c33..ad15414b24 100644 Binary files a/public/res/logo-maskable/logo-maskable-60x60.png and b/public/res/logo-maskable/logo-maskable-60x60.png differ diff --git a/public/res/logo-maskable/logo-maskable-72x72.png b/public/res/logo-maskable/logo-maskable-72x72.png index 90806e9b01..265c13b93c 100644 Binary files a/public/res/logo-maskable/logo-maskable-72x72.png and b/public/res/logo-maskable/logo-maskable-72x72.png differ diff --git a/public/res/logo-maskable/logo-maskable-76x76.png b/public/res/logo-maskable/logo-maskable-76x76.png index 04645074ef..1ef2ec3fbb 100644 Binary files a/public/res/logo-maskable/logo-maskable-76x76.png and b/public/res/logo-maskable/logo-maskable-76x76.png differ diff --git a/public/res/logo-maskable/logo-maskable-96x96.png b/public/res/logo-maskable/logo-maskable-96x96.png index b066c991d4..37bd53de99 100644 Binary files a/public/res/logo-maskable/logo-maskable-96x96.png and b/public/res/logo-maskable/logo-maskable-96x96.png differ diff --git a/public/res/logo/logo-144x144.png b/public/res/logo/logo-144x144.png index 85456a23d3..9de06231f6 100644 Binary files a/public/res/logo/logo-144x144.png and b/public/res/logo/logo-144x144.png differ diff --git a/public/res/logo/logo-192x192.png b/public/res/logo/logo-192x192.png index 40004e6e7c..90da80d7fc 100644 Binary files a/public/res/logo/logo-192x192.png and b/public/res/logo/logo-192x192.png differ diff --git a/public/res/logo/logo-256x256.png b/public/res/logo/logo-256x256.png index f25497e848..bd6a3f54f9 100644 Binary files a/public/res/logo/logo-256x256.png and b/public/res/logo/logo-256x256.png differ diff --git a/public/res/logo/logo-36x36.png b/public/res/logo/logo-36x36.png index a861a47175..04c746f485 100644 Binary files a/public/res/logo/logo-36x36.png and b/public/res/logo/logo-36x36.png differ diff --git a/public/res/logo/logo-384x384.png b/public/res/logo/logo-384x384.png index f65fd79f78..d8845ba93d 100644 Binary files a/public/res/logo/logo-384x384.png and b/public/res/logo/logo-384x384.png differ diff --git a/public/res/logo/logo-48x48.png b/public/res/logo/logo-48x48.png index 4a1309e7ef..e9e9d8c0c8 100644 Binary files a/public/res/logo/logo-48x48.png and b/public/res/logo/logo-48x48.png differ diff --git a/public/res/logo/logo-512x512.png b/public/res/logo/logo-512x512.png index 4638bcb333..c9dc1f0eea 100644 Binary files a/public/res/logo/logo-512x512.png and b/public/res/logo/logo-512x512.png differ diff --git a/public/res/logo/logo-72x72.png b/public/res/logo/logo-72x72.png index 8dfdb80a25..044d6a7b5d 100644 Binary files a/public/res/logo/logo-72x72.png and b/public/res/logo/logo-72x72.png differ diff --git a/public/res/logo/logo-96x96.png b/public/res/logo/logo-96x96.png index 97a5964046..a09a2c960a 100644 Binary files a/public/res/logo/logo-96x96.png and b/public/res/logo/logo-96x96.png differ diff --git a/public/res/svg/highlight.svg b/public/res/svg/highlight.svg index 1c2bfcf105..0ad405f742 100644 --- a/public/res/svg/highlight.svg +++ b/public/res/svg/highlight.svg @@ -1,6 +1,69 @@ - - - - - - + + diff --git a/public/res/svg/logo-maskable.svg b/public/res/svg/logo-maskable.svg index 16ad163652..a57b179285 100644 --- a/public/res/svg/logo-maskable.svg +++ b/public/res/svg/logo-maskable.svg @@ -1,5 +1,52 @@ - - - - - + + diff --git a/public/res/svg/logo.svg b/public/res/svg/logo.svg index 8de551f504..b31ca21829 100644 --- a/public/res/svg/logo.svg +++ b/public/res/svg/logo.svg @@ -1,5 +1,92 @@ - - - - - + + diff --git a/public/res/svg/unread.svg b/public/res/svg/unread.svg index b320ace7b7..5c342ca578 100644 --- a/public/res/svg/unread.svg +++ b/public/res/svg/unread.svg @@ -1,6 +1,73 @@ - - - - - - + + diff --git a/public/unread.svg b/public/unread.svg new file mode 100644 index 0000000000..5c342ca578 --- /dev/null +++ b/public/unread.svg @@ -0,0 +1,73 @@ + + diff --git a/src-tauri/gen/android/app/build.gradle.kts b/src-tauri/gen/android/app/build.gradle.kts index 90abfc67a0..4ee558fe09 100644 --- a/src-tauri/gen/android/app/build.gradle.kts +++ b/src-tauri/gen/android/app/build.gradle.kts @@ -25,20 +25,6 @@ android { versionCode = tauriProperties.getProperty("tauri.android.versionCode", "1").toInt() versionName = tauriProperties.getProperty("tauri.android.versionName", "1.0") } - signingConfigs { - create("release") { - val keystorePropertiesFile = rootProject.file("keystore.properties") - if (keystorePropertiesFile.exists()) { - val keystoreProperties = Properties() - keystoreProperties.load(FileInputStream(keystorePropertiesFile)) - - keyAlias = keystoreProperties["keyAlias"] as String - keyPassword = keystoreProperties["password"] as String - storeFile = file(keystoreProperties["storeFile"] as String) - storePassword = keystoreProperties["password"] as String - } - } - } buildTypes { getByName("debug") { manifestPlaceholders["usesCleartextTraffic"] = "true" diff --git a/src/app/components/sidebar/Sidebar.css.ts b/src/app/components/sidebar/Sidebar.css.ts index b7fc9ca3b4..b486ea2545 100644 --- a/src/app/components/sidebar/Sidebar.css.ts +++ b/src/app/components/sidebar/Sidebar.css.ts @@ -8,7 +8,7 @@ export const Sidebar = style([ DefaultReset, { width: toRem(66), - backgroundColor: color.Background.Container, + backgroundColor: "#232323", borderRight: `${config.borderWidth.B300} solid ${color.Background.ContainerLine}`, display: 'flex', diff --git a/src/app/components/splash-screen/SplashScreen.tsx b/src/app/components/splash-screen/SplashScreen.tsx index 4ddf2ca8a5..371f955c7f 100644 --- a/src/app/components/splash-screen/SplashScreen.tsx +++ b/src/app/components/splash-screen/SplashScreen.tsx @@ -21,7 +21,7 @@ export function SplashScreen({ children }: SplashScreenProps) { justifyContent="Center" > - Sable + Mable diff --git a/src/app/features/settings/about/About.tsx b/src/app/features/settings/about/About.tsx index 94518183f3..05be62c503 100644 --- a/src/app/features/settings/about/About.tsx +++ b/src/app/features/settings/about/About.tsx @@ -255,22 +255,22 @@ export function About({ requestBack, requestClose }: Readonly) { Sable logo - Sable + Mable {`v${APP_VERSION}${devLabel}${buildLabel}`} - An almost stable Matrix client. + A mostly stable Matrix client. diff --git a/src/app/pages/auth/AuthLayout.tsx b/src/app/pages/auth/AuthLayout.tsx index 63dc56d17d..543a415f10 100644 --- a/src/app/pages/auth/AuthLayout.tsx +++ b/src/app/pages/auth/AuthLayout.tsx @@ -214,8 +214,8 @@ export function AuthLayout() {
- Sable Logo - Sable + Mable Logo + Mable {isAddingAccount && ( diff --git a/src/app/pages/client/WelcomePage.tsx b/src/app/pages/client/WelcomePage.tsx index 70ee8bffba..871c11389b 100644 --- a/src/app/pages/client/WelcomePage.tsx +++ b/src/app/pages/client/WelcomePage.tsx @@ -1,5 +1,4 @@ -import { Box, Button, Text, config, toRem } from 'folds'; -import { Code, Heart, menuIcon } from '$components/icons/phosphor'; +import { Box, Button, Icon, Icons, Text, config, toRem } from 'folds'; import { Page, PageHero, PageHeroSection } from '$components/page'; import { versionLabel } from '$utils/platform'; import LogoSVG from '$public/res/svg/logo.svg'; @@ -15,13 +14,13 @@ export function WelcomePage() { > } - title="Welcome to Sable" + icon={Mable Logo} + title="Welcome to Mable" subTitle={ - An almost stable Matrix client.{' '} + A M(ostly st)able Matrix client. Based on the hard work of the Cinny & Sable development teams{' '} @@ -34,10 +33,10 @@ export function WelcomePage() { @@ -60,13 +59,13 @@ export function WelcomePage() { diff --git a/src/app/pages/client/sidebar/UserQuickTools.css.ts b/src/app/pages/client/sidebar/UserQuickTools.css.ts index f085e5fc81..5c5beaf1fd 100644 --- a/src/app/pages/client/sidebar/UserQuickTools.css.ts +++ b/src/app/pages/client/sidebar/UserQuickTools.css.ts @@ -2,8 +2,9 @@ import { style } from '@vanilla-extract/css'; import { color, config, toRem } from 'folds'; export const UserQuickTools = style({ - backgroundColor: color.Surface.Container, - color: color.Surface.OnContainer, + backgroundColor: "#2b2b2b", + color: color.Background.OnContainer, + position: 'absolute', zIndex: '1000', height: toRem(74), bottom: '0', diff --git a/src/app/styles/themes.css b/src/app/styles/themes.css index d936dcd964..4888d50446 100755 --- a/src/app/styles/themes.css +++ b/src/app/styles/themes.css @@ -1,138 +1,138 @@ /* --- Light --- */ .light-theme { /* Background */ - --sable-bg-container: #ffffff; - --sable-bg-container-hover: #f4f4f5; - --sable-bg-container-active: #e4e4e7; - --sable-bg-container-line: #d4d4d8; - --sable-bg-on-container: #18181b; + --sable-bg-container: #f9f9f9; + --sable-bg-container-hover: #e5e5e5; + --sable-bg-container-active: #d9d9d9; + --sable-bg-container-line: #e9e9e9; + --sable-bg-on-container: #454545; /* Surface */ - --sable-surface-container: #f4f4f5; - --sable-surface-container-hover: #ffffff; - --sable-surface-container-active: #e4e4e7; - --sable-surface-container-line: #d4d4d8; - --sable-surface-on-container: #18181b; + --sable-surface-container: #ffffff; + --sable-surface-container-hover: #f9f9f9; + --sable-surface-container-active: #e5e5e5; + --sable-surface-container-line: #e9e9e9; + --sable-surface-on-container: #222; /* Surface Variant */ - --sable-surface-var-container: #e4e4e7; - --sable-surface-var-container-hover: #d4d4d8; - --sable-surface-var-container-active: #a1a1aa; - --sable-surface-var-container-line: #71717a; - --sable-surface-var-on-container: #27272a; + --sable-surface-var-container: #f9f9f9; + --sable-surface-var-container-hover: #e5e5e5; + --sable-surface-var-container-active: #d9d9d9; + --sable-surface-var-container-line: #e9e9e9; + --sable-surface-var-on-container: #000000; /* Primary */ - --sable-primary-main: #6e56cf; - --sable-primary-main-hover: #644ec1; - --sable-primary-main-active: #5b47b3; - --sable-primary-main-line: #5240a5; + --sable-primary-main: #d59d18; + --sable-primary-main-hover: #d59d18; + --sable-primary-main-active: #144bb5; + --sable-primary-main-line: #d59d18; --sable-primary-on-main: #ffffff; - --sable-primary-container: #ded9e6; - --sable-primary-container-hover: #d3cde0; - --sable-primary-container-active: #c8c1d9; - --sable-primary-container-line: #bdb6d3; - --sable-primary-on-container: #2d235c; + --sable-primary-container: #f6e6cd; + --sable-primary-container-hover: #f9efdc; + --sable-primary-container-active: #f2e2c6; + --sable-primary-container-line: #f0e1be; + --sable-primary-on-container: #956111; /* Secondary */ - --sable-sec-main: #514861; - --sable-sec-main-hover: #453e54; - --sable-sec-main-active: #3b3447; - --sable-sec-main-line: #312e3b; + --sable-sec-main: #000000; + --sable-sec-main-hover: #1a1a1a; + --sable-sec-main-active: #262626; + --sable-sec-main-line: #333333; --sable-sec-on-main: #ffffff; - --sable-sec-container: #eae8f0; - --sable-sec-container-hover: #dedce8; - --sable-sec-container-active: #d2d0e0; - --sable-sec-container-line: #c6c4d8; - --sable-sec-on-container: #2d235c; + --sable-sec-container: #d9d9d9; + --sable-sec-container-hover: #cccccc; + --sable-sec-container-active: #bfbfbf; + --sable-sec-container-line: #b2b2b2; + --sable-sec-on-container: #0d0d0d; /* Success */ - --sable-success-main: #017343; - --sable-success-main-hover: #01683c; - --sable-success-main-active: #016239; - --sable-success-main-line: #015c36; + --sable-success-main: #00844c; + --sable-success-main-hover: #007744; + --sable-success-main-active: #007041; + --sable-success-main-line: #006a3d; --sable-success-on-main: #ffffff; - --sable-success-container: #bfdcd0; - --sable-success-container-hover: #b3d5c7; - --sable-success-container-active: #a6cebd; - --sable-success-container-line: #99c7b4; - --sable-success-on-container: #01512f; + --sable-success-container: #e5f3ed; + --sable-success-container-hover: #d9ede4; + --sable-success-container-active: #cce6db; + --sable-success-container-line: #bfe0d2; + --sable-success-on-container: #005c35; /* Warning */ - --sable-warn-main: #864300; - --sable-warn-main-hover: #793c00; - --sable-warn-main-active: #723900; - --sable-warn-main-line: #6b3600; + --sable-warn-main: #a85400; + --sable-warn-main-hover: #974c00; + --sable-warn-main-active: #8f4700; + --sable-warn-main-line: #864300; --sable-warn-on-main: #ffffff; - --sable-warn-container: #e1d0bf; - --sable-warn-container-hover: #dbc7b2; - --sable-warn-container-active: #d5bda6; - --sable-warn-container-line: #cfb499; - --sable-warn-on-container: #5e2f00; + --sable-warn-container: #f6eee5; + --sable-warn-container-hover: #f2e5d9; + --sable-warn-container-active: #eeddcc; + --sable-warn-container-line: #e9d4bf; + --sable-warn-on-container: #763b00; /* Critical */ - --sable-crit-main: #9d0f0f; - --sable-crit-main-hover: #8d0e0e; - --sable-crit-main-active: #850d0d; - --sable-crit-main-line: #7e0c0c; + --sable-crit-main: #c40e0e; + --sable-crit-main-hover: #ac0909; + --sable-crit-main-active: #a60c0c; + --sable-crit-main-line: #9c0b0b; --sable-crit-on-main: #ffffff; - --sable-crit-container: #e7c3c3; - --sable-crit-container-hover: #e2b7b7; - --sable-crit-container-active: #ddabab; - --sable-crit-container-line: #d89f9f; - --sable-crit-on-container: #6e0b0b; + --sable-crit-container: #f9e7e7; + --sable-crit-container-hover: #f6dbdb; + --sable-crit-container-active: #f3cfcf; + --sable-crit-container-line: #f0c3c3; + --sable-crit-on-container: #890a0a; /* Other */ - --sable-focus-ring: rgba(110, 86, 207, 0.4); - --sable-shadow: rgba(0, 0, 0, 0.1); - --sable-overlay: rgba(0, 0, 0, 0.4); + --sable-focus-ring: rgba(0 0 0 / 50%); + --sable-shadow: rgba(0 0 0 / 20%); + --sable-overlay: rgba(0 0 0 / 50%); } /* --- Dark --- */ .dark-theme { /* Background */ - --sable-bg-container: #1b1a21; - --sable-bg-container-hover: #24232c; - --sable-bg-container-active: #2d2c36; - --sable-bg-container-line: #363541; - --sable-bg-on-container: #eae8f0; + --sable-bg-container: #262626; + --sable-bg-container-hover: #303030; + --sable-bg-container-active: #333333; + --sable-bg-container-line: #353535; + --sable-bg-on-container: #f2f2f2; /* Surface */ - --sable-surface-container: #24232c; - --sable-surface-container-hover: #2d2c36; - --sable-surface-container-active: #363541; - --sable-surface-container-line: #403f4c; - --sable-surface-on-container: #eae8f0; + --sable-surface-container: #303030; + --sable-surface-container-hover: #333333; + --sable-surface-container-active: #404040; + --sable-surface-container-line: #3E3E3E; + --sable-surface-on-container: #f2f2f2; /* Surface Variant */ - --sable-surface-var-container: #121116; - --sable-surface-var-container-hover: #1b1a21; - --sable-surface-var-container-active: #24232c; - --sable-surface-var-container-line: #363541; - --sable-surface-var-on-container: #bdb6ec; + --sable-surface-var-container: #333333; + --sable-surface-var-container-hover: #404040; + --sable-surface-var-container-active: #4d4d4d; + --sable-surface-var-container-line: #3E3E3E; + --sable-surface-var-on-container: #f2f2f2; /* Primary */ - --sable-primary-main: #bdb6ec; - --sable-primary-main-hover: #a9a1e6; - --sable-primary-main-active: #958be0; - --sable-primary-main-line: #8175da; - --sable-primary-on-main: #1b1a21; - --sable-primary-container: #2d235c; - --sable-primary-container-hover: #382d70; - --sable-primary-container-active: #433784; - --sable-primary-container-line: #4e4198; - --sable-primary-on-container: #e3e1f7; + --sable-primary-main: #f7d7ae; + --sable-primary-main-hover: #f7d7ae; + --sable-primary-main-active: #ada3e8; + --sable-primary-main-line: #f7d7ae; + --sable-primary-on-main: #2c2843; + --sable-primary-container: #7a6049; + --sable-primary-container-hover: #947553; + --sable-primary-container-active: #6d563d; + --sable-primary-container-line: #756142; + --sable-primary-on-container: #f7f3e1; /* Secondary */ - --sable-sec-main: #9992ac; - --sable-sec-main-hover: #aaa4ba; - --sable-sec-main-active: #bbb6c8; - --sable-sec-main-line: #ccc8d6; - --sable-sec-on-main: #1b1a21; - --sable-sec-container: #2d2c36; - --sable-sec-container-hover: #363541; - --sable-sec-container-active: #403f4c; - --sable-sec-container-line: #4b4a58; - --sable-sec-on-container: #eae8f0; + --sable-sec-main: #ffffff; + --sable-sec-main-hover: #e5e5e5; + --sable-sec-main-active: #d9d9d9; + --sable-sec-main-line: #cccccc; + --sable-sec-on-main: #262626; + --sable-sec-container: #404040; + --sable-sec-container-hover: #4d4d4d; + --sable-sec-container-active: #595959; + --sable-sec-container-line: #666666; + --sable-sec-on-container: #f2f2f2; /* Success */ --sable-success-main: #85e0ba; @@ -171,7 +171,7 @@ --sable-crit-on-container: #f5d6d6; /* Other */ - --sable-focus-ring: rgba(189, 182, 236, 0.5); - --sable-shadow: rgba(0, 0, 0, 0.4); - --sable-overlay: rgba(15, 14, 18, 0.85); + --sable-focus-ring: rgba(255, 255, 255, 0.5); + --sable-shadow: rgba(0, 0, 0, 1); + --sable-overlay: rgba(0, 0, 0, 0.8); } diff --git a/src/index.css b/src/index.css index d102f5ef4e..60224ed6b3 100755 --- a/src/index.css +++ b/src/index.css @@ -1,39 +1,49 @@ @import '@sableclient/twemoji-font'; @import 'folds/dist/style.css' layer(folds); + @layer sable-reset, folds; +@font-face { + font-family: AdwaitaSans; + src: + url('../public/font/AdwaitaSans-Regular.ttf'); + font-display: swap; +} + +@font-face { + font-family: AdwaitaMono; + src: + url('../public/font/AdwaitaMono-Regular.ttf'); + font-display: swap; +} +@font-face { + font-family:AdwaitaSans; + src:url(/mable/assets/AdwaitaSans-Regular-CowLxMoJ.ttf); + font-display:swap +} +@font-face { + font-family:AdwaitaMono; + src:url(/mable/assets/AdwaitaMono-Regular-wsVtlayZ.ttf); + font-display:swap +} +:root { + --tc-link: hsl(39.4, 100%, 45.1%); +} @layer sable-reset { :root { - --tc-link: hsl(213deg 100% 45%); - - /* user mxid colors */ - --mx-uc-1: hsl(208, 100%, 45%); - --mx-uc-2: hsl(302, 100%, 30%); - --mx-uc-3: hsl(163, 100%, 30%); - --mx-uc-4: hsl(343, 100%, 45%); - --mx-uc-5: hsl(24, 100%, 45%); - --mx-uc-6: hsl(181, 100%, 30%); - --mx-uc-7: hsl(242, 100%, 45%); - --mx-uc-8: hsl(94, 100%, 35%); - - --font-emoji: 'Twemoji_DISABLED'; - --font-secondary: 'Nunito Variable', var(--font-emoji), sans-serif; - --font-monospace: 'Space Mono', monospace; - } - - .dark-theme, - .sable-remote-kind-dark { - --tc-link: hsl(213deg 100% 80%); + --tc-link: hsl(213deg 100% 45%); + --font-emoji: 'Twemoji_DISABLED'; + --font-secondary: "AdwaitaSans", var(--font-emoji), sans-serif; + --font-monospace: "AdwaitaMono", monospace +} - --mx-uc-1: hsl(260, 100%, 75%); - --mx-uc-2: hsl(320, 100%, 75%); - --mx-uc-3: hsl(180, 100%, 65%); - --mx-uc-4: hsl(150, 100%, 70%); - --mx-uc-5: hsl(200, 100%, 75%); - --mx-uc-6: hsl(280, 80%, 70%); - --mx-uc-7: hsl(40, 100%, 75%); - --mx-uc-8: hsl(0, 100%, 75%); +.dark-theme, +.sable-remote-kind-dark { + --tc-link: hsl(37.03deg 100% 80%); + --font-secondary: "AdwaitaSans", var(--font-emoji), sans-serif; + --font-monospace: "AdwaitaMono", monospace +} --font-secondary: 'Nunito Variable', var(--font-emoji), sans-serif; --font-monospace: 'Space Mono', monospace;