├── .env.example ├── .eslintignore ├── .eslintrc.cjs ├── .github ├── renovate.json └── workflows │ ├── ci.yml │ └── release.yml ├── .gitignore ├── .npmrc ├── .prettierignore ├── .prettierrc ├── .stylelintignore ├── .stylelintrc ├── .vscode ├── extensions.json └── settings.json ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── assets ├── apple-dark.png ├── apple-light.png ├── dashboard-dark.png ├── dashboard-light.png ├── linux.png ├── logo.png └── windows.png ├── package.json ├── pnpm-lock.yaml ├── src-tauri ├── .gitignore ├── Cargo.lock ├── Cargo.toml ├── Info.plist ├── build.rs ├── icons │ ├── 128x128.png │ ├── 128x128@2x.png │ ├── 32x32.png │ ├── Square107x107Logo.png │ ├── Square142x142Logo.png │ ├── Square150x150Logo.png │ ├── Square284x284Logo.png │ ├── Square30x30Logo.png │ ├── Square310x310Logo.png │ ├── Square44x44Logo.png │ ├── Square71x71Logo.png │ ├── Square89x89Logo.png │ ├── StoreLogo.png │ ├── icon.icns │ ├── icon.ico │ ├── icon.png │ ├── tray-base-macos.png │ ├── tray-base.png │ ├── tray-new-macos.png │ └── tray-new.png ├── src │ ├── commands.rs │ ├── main.rs │ └── title_bar.rs └── tauri.conf.json ├── src ├── app.d.ts ├── app.html ├── lib │ ├── components │ │ ├── common │ │ │ ├── AnimatedLogo.svelte │ │ │ ├── Button.svelte │ │ │ ├── DragRegion.svelte │ │ │ ├── IconButton.svelte │ │ │ ├── InlineSelect.svelte │ │ │ ├── Input.svelte │ │ │ ├── Modal.svelte │ │ │ ├── ScrollbarContainer.svelte │ │ │ ├── Select.svelte │ │ │ ├── ShrinkableWrapper.svelte │ │ │ ├── Switch.svelte │ │ │ ├── Tooltip.svelte │ │ │ └── index.ts │ │ ├── dashboard │ │ │ ├── Banner.svelte │ │ │ ├── LoadingScreen.svelte │ │ │ ├── Main.svelte │ │ │ ├── SyncPill.svelte │ │ │ ├── index.ts │ │ │ ├── notifications │ │ │ │ ├── DoneModal.svelte │ │ │ │ ├── Notification.svelte │ │ │ │ ├── NotificationColumn.svelte │ │ │ │ ├── NotificationDescription.svelte │ │ │ │ ├── NotificationLabels.svelte │ │ │ │ ├── NotificationList.svelte │ │ │ │ ├── NotificationPlaceholder.svelte │ │ │ │ ├── NotificationStatus.svelte │ │ │ │ └── index.ts │ │ │ ├── priorities │ │ │ │ ├── Priorities.svelte │ │ │ │ ├── PriorityItem.svelte │ │ │ │ └── index.ts │ │ │ └── sidebar │ │ │ │ ├── Sidebar.svelte │ │ │ │ ├── SidebarProviders.svelte │ │ │ │ ├── SidebarSearch.svelte │ │ │ │ ├── SidebarSection.svelte │ │ │ │ ├── TypeFilters.svelte │ │ │ │ ├── WatchedPersons.svelte │ │ │ │ ├── WatchedRepos.svelte │ │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── landing │ │ │ ├── DownloadButton.svelte │ │ │ └── index.ts │ │ ├── login │ │ │ ├── GithubLoginButton.svelte │ │ │ ├── GitlabLoginButton.svelte │ │ │ └── index.ts │ │ └── settings │ │ │ ├── App.svelte │ │ │ ├── Preferences.svelte │ │ │ ├── Settings.svelte │ │ │ ├── accounts │ │ │ ├── Account.svelte │ │ │ ├── Accounts.svelte │ │ │ ├── LogOutButton.svelte │ │ │ └── index.ts │ │ │ ├── github-settings │ │ │ ├── GithubSettings.svelte │ │ │ ├── PatItem.svelte │ │ │ └── index.ts │ │ │ ├── gitlab-settings │ │ │ ├── GitlabRepos.svelte │ │ │ ├── GitlabSettings.svelte │ │ │ ├── RepoInput.svelte │ │ │ └── index.ts │ │ │ └── index.ts │ ├── features │ │ ├── createGithubNotificationData.ts │ │ ├── createGitlabNotificationData.ts │ │ ├── delayed-hover.ts │ │ ├── drag-actions.ts │ │ ├── fetchGithub.ts │ │ ├── fetchGitlab.ts │ │ ├── getGithubDiscussionData.ts │ │ ├── index.ts │ │ ├── intersection-action.ts │ │ └── storage.ts │ ├── helpers │ │ ├── debounce.ts │ │ ├── formatRelativeDate.ts │ │ ├── getAppVersion.ts │ │ ├── getIcon.ts │ │ ├── getNotificationIcon.ts │ │ ├── index.ts │ │ ├── openDesktopApp.ts │ │ ├── priorities.ts │ │ ├── removeMarkdownSymbols.ts │ │ └── shadeColor.ts │ ├── icons │ │ ├── AnsweredDiscussionIcon.svelte │ │ ├── ArrowRightIcon.svelte │ │ ├── ArrowUpIcon.svelte │ │ ├── CheckIcon.svelte │ │ ├── ClosedIssueIcon.svelte │ │ ├── ClosedPullRequestIcon.svelte │ │ ├── CommitIcon.svelte │ │ ├── CompletedIssueIcon.svelte │ │ ├── CrossIcon.svelte │ │ ├── DiscussionIcon.svelte │ │ ├── DoubleArrowIcon.svelte │ │ ├── DoubleCheckIcon.svelte │ │ ├── DraftPullRequestIcon.svelte │ │ ├── ExclamationMarkIcon.svelte │ │ ├── ExternalLinkIcon.svelte │ │ ├── GearIcon.svelte │ │ ├── GithubIcon.svelte │ │ ├── GitlabIcon.svelte │ │ ├── HeartIcon.svelte │ │ ├── LightningIcon.svelte │ │ ├── LinuxIcon.svelte │ │ ├── MacosIcon.svelte │ │ ├── MergedPullRequestIcon.svelte │ │ ├── MuteIcon.svelte │ │ ├── MutedIcon.svelte │ │ ├── OpenIssueIcon.svelte │ │ ├── OpenPullRequestIcon.svelte │ │ ├── PersonIcon.svelte │ │ ├── PinIcon.svelte │ │ ├── PlusIcon.svelte │ │ ├── PriorityDownIcon.svelte │ │ ├── PriorityIcon.svelte │ │ ├── PriorityUpIcon.svelte │ │ ├── RefreshIcon.svelte │ │ ├── ReleaseIcon.svelte │ │ ├── RepositoryIcon.svelte │ │ ├── RestoreIcon.svelte │ │ ├── SearchIcon.svelte │ │ ├── SmallArrowIcon.svelte │ │ ├── SparklesIcon.svelte │ │ ├── ThreeDotsIcon.svelte │ │ ├── TrashIcon.svelte │ │ ├── UnpinIcon.svelte │ │ ├── UnreadIcon.svelte │ │ ├── WindowsIcon.svelte │ │ ├── WorkflowFailIcon.svelte │ │ ├── WorkflowSuccessIcon.svelte │ │ ├── XIcon.svelte │ │ └── index.ts │ ├── stores │ │ ├── index.ts │ │ └── stores.ts │ └── types │ │ ├── common-types.ts │ │ ├── github-types.ts │ │ ├── gitlab-types.ts │ │ ├── index.ts │ │ └── type-helpers.ts ├── routes │ ├── (app) │ │ ├── +layout.svelte │ │ ├── dashboard │ │ │ └── +page.svelte │ │ ├── deeplink │ │ │ └── +page.svelte │ │ └── login │ │ │ └── +page.svelte │ ├── (tray) │ │ └── tray │ │ │ └── +page.svelte │ ├── +layout.ts │ ├── +page.svelte │ ├── auth │ │ ├── github │ │ │ ├── callback │ │ │ │ └── +server.ts │ │ │ └── login │ │ │ │ └── +server.ts │ │ └── gitlab │ │ │ ├── callback │ │ │ └── +server.ts │ │ │ ├── login │ │ │ └── +server.ts │ │ │ └── refresh │ │ │ └── +server.ts │ ├── download │ │ └── [os] │ │ │ └── +server.ts │ └── version │ │ └── [target] │ │ └── [version] │ │ └── +server.ts └── styles │ ├── _base.scss │ ├── _fonts.scss │ ├── _mixins.scss │ ├── _reset.scss │ ├── _screens.scss │ ├── _themes.scss │ ├── _typography.scss │ └── _variables.scss ├── static ├── favicon.ico ├── fonts │ ├── Inter-Regular.ttf │ └── Inter-SemiBold.ttf ├── images │ ├── gitlight-dark.webp │ ├── gitlight-light.webp │ └── logo.webp └── rive │ └── logo.riv ├── svelte.config.js ├── tsconfig.json └── vite.config.ts /.env.example: -------------------------------------------------------------------------------- 1 | AUTH_GITHUB_ID= 2 | AUTH_GITHUB_SECRET= 3 | AUTH_GITLAB_ID= 4 | AUTH_GITLAB_SECRET= 5 | AUTH_SECRET= 6 | PUBLIC_SITE_URL= 7 | 8 | # Only needed to build the desktop app 9 | TAURI_PRIVATE_KEY= 10 | TAURI_KEY_PASSWORD= 11 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | /src-tauri 10 | 11 | # Ignore files for PNPM, NPM and YARN 12 | pnpm-lock.yaml 13 | package-lock.json 14 | yarn.lock 15 | -------------------------------------------------------------------------------- /.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | /** @type { import("eslint").Linter.Config } */ 2 | module.exports = { 3 | root: true, 4 | extends: [ 5 | 'eslint:recommended', 6 | 'plugin:@typescript-eslint/recommended', 7 | 'plugin:svelte/recommended', 8 | 'prettier' 9 | ], 10 | parser: '@typescript-eslint/parser', 11 | plugins: ['@typescript-eslint', 'import'], 12 | parserOptions: { 13 | sourceType: 'module', 14 | ecmaVersion: 2020, 15 | extraFileExtensions: ['.svelte'] 16 | }, 17 | ignorePatterns: ['*.cjs', 'svelte.config.js'], 18 | env: { 19 | browser: true, 20 | es2017: true, 21 | node: true 22 | }, 23 | overrides: [ 24 | { 25 | files: ['*.svelte'], 26 | parser: 'svelte-eslint-parser', 27 | parserOptions: { 28 | parser: '@typescript-eslint/parser' 29 | } 30 | } 31 | ], 32 | rules: { 33 | '@typescript-eslint/no-unused-vars': [1, { argsIgnorePattern: '^_' }], 34 | 'no-console': ['warn', { allow: ['error'] }], 35 | 'no-self-assign': 'off', 36 | 'import/order': [ 37 | 'warn', 38 | { 39 | groups: ['external', 'unknown', 'internal', 'sibling', 'parent'], 40 | pathGroups: [ 41 | { pattern: '$.*', group: 'unknown' }, 42 | { pattern: '$lib/*', group: 'internal' } 43 | ], 44 | alphabetize: { order: 'asc', caseInsensitive: true }, 45 | 'newlines-between': 'never' 46 | } 47 | ] 48 | } 49 | }; 50 | -------------------------------------------------------------------------------- /.github/renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:base", "group:allNonMajor"], 4 | "labels": ["dependency"], 5 | "rangeStrategy": "bump", 6 | "enabled": false 7 | } 8 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - main 6 | pull_request: 7 | env: 8 | AUTH_GITHUB_ID: ${{ secrets.AUTH_GITHUB_ID }} 9 | AUTH_GITHUB_SECRET: ${{ secrets.AUTH_GITHUB_SECRET }} 10 | AUTH_GITLAB_ID: ${{ secrets.AUTH_GITLAB_ID }} 11 | AUTH_GITLAB_SECRET: ${{ secrets.AUTH_GITLAB_SECRET }} 12 | AUTH_SECRET: ${{ secrets.AUTH_SECRET }} 13 | PUBLIC_SITE_URL: ${{ secrets.PUBLIC_SITE_URL }} 14 | TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} 15 | TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} 16 | jobs: 17 | lint-ts: 18 | runs-on: ubuntu-latest 19 | steps: 20 | - uses: actions/checkout@v4 21 | - uses: pnpm/action-setup@v4 22 | with: 23 | version: 8 24 | - name: Use Node.js 18 25 | uses: actions/setup-node@v4 26 | with: 27 | node-version: 18 28 | cache: 'pnpm' 29 | - name: Install dependencies 30 | run: pnpm install 31 | - name: Lint TypeScript 32 | run: pnpm lint:ts 33 | lint-rs: 34 | runs-on: ubuntu-latest 35 | steps: 36 | - uses: actions/checkout@v4 37 | - uses: pnpm/action-setup@v4 38 | with: 39 | version: 8 40 | - name: Install Tauri dependencies 41 | run: | 42 | sudo apt-get update 43 | sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev 44 | - name: Rust setup 45 | uses: dtolnay/rust-toolchain@stable 46 | - name: Rust cache 47 | uses: swatinem/rust-cache@v2 48 | with: 49 | workspaces: './src-tauri -> target' 50 | - name: Lint Rust 51 | run: pnpm lint:rs 52 | typecheck: 53 | runs-on: ubuntu-latest 54 | steps: 55 | - uses: actions/checkout@v4 56 | - uses: pnpm/action-setup@v4 57 | with: 58 | version: 8 59 | - name: Use Node.js 18 60 | uses: actions/setup-node@v4 61 | with: 62 | node-version: 18 63 | cache: 'pnpm' 64 | - name: Install dependencies 65 | run: pnpm install 66 | - name: Typecheck 67 | run: pnpm typecheck 68 | build-front: 69 | runs-on: ubuntu-latest 70 | steps: 71 | - uses: actions/checkout@v4 72 | - uses: pnpm/action-setup@v4 73 | with: 74 | version: 8 75 | - name: Use Node.js 18 76 | uses: actions/setup-node@v4 77 | with: 78 | node-version: 18 79 | cache: 'pnpm' 80 | - name: Install dependencies 81 | run: pnpm install 82 | - name: Build 83 | run: pnpm build 84 | build-app: 85 | # Tauri build from forks fails because no access to secrets 86 | if: ${{ !github.event.pull_request.head.repo.fork }} 87 | runs-on: ubuntu-latest 88 | steps: 89 | - uses: actions/checkout@v4 90 | - name: Install Tauri dependencies 91 | run: | 92 | sudo apt-get update 93 | sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev 94 | - name: Rust setup 95 | uses: dtolnay/rust-toolchain@stable 96 | - name: Rust cache 97 | uses: swatinem/rust-cache@v2 98 | with: 99 | workspaces: './src-tauri -> target' 100 | - uses: pnpm/action-setup@v4 101 | with: 102 | version: 8 103 | - name: Use Node.js 18 104 | uses: actions/setup-node@v4 105 | with: 106 | node-version: 18 107 | cache: 'pnpm' 108 | - name: Install frontend dependencies 109 | run: pnpm install 110 | - name: Build app 111 | run: pnpm tauri build 112 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | on: 3 | push: 4 | branches: 5 | - main 6 | workflow_dispatch: 7 | env: 8 | AUTH_GITHUB_ID: ${{ secrets.AUTH_GITHUB_ID }} 9 | AUTH_GITHUB_SECRET: ${{ secrets.AUTH_GITHUB_SECRET }} 10 | AUTH_GITLAB_ID: ${{ secrets.AUTH_GITLAB_ID }} 11 | AUTH_GITLAB_SECRET: ${{ secrets.AUTH_GITLAB_SECRET }} 12 | AUTH_SECRET: ${{ secrets.AUTH_SECRET }} 13 | PUBLIC_SITE_URL: ${{ secrets.PUBLIC_SITE_URL }} 14 | TAURI_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }} 15 | TAURI_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }} 16 | jobs: 17 | release: 18 | if: contains(github.event.head_commit.message, 'release') 19 | strategy: 20 | fail-fast: false 21 | matrix: 22 | include: 23 | - os: macos-latest 24 | target: aarch64-apple-darwin 25 | - os: macos-latest 26 | target: x86_64-apple-darwin 27 | - os: ubuntu-20.04 28 | - os: windows-latest 29 | runs-on: ${{ matrix.os }} 30 | steps: 31 | - uses: actions/checkout@v4 32 | - name: Install Tauri dependencies (ubuntu only) 33 | if: matrix.os == 'ubuntu-20.04' 34 | run: | 35 | sudo apt-get update 36 | sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev libayatana-appindicator3-dev librsvg2-dev 37 | - name: Rust setup 38 | uses: dtolnay/rust-toolchain@stable 39 | - name: Rust cache 40 | uses: swatinem/rust-cache@v2 41 | with: 42 | workspaces: './src-tauri -> target' 43 | - if: matrix.target 44 | run: rustup target add ${{ matrix.target }} 45 | - uses: pnpm/action-setup@v4 46 | with: 47 | version: 8 48 | - name: Use Node.js 18 49 | uses: actions/setup-node@v4 50 | with: 51 | node-version: 18 52 | cache: 'pnpm' 53 | - name: Install frontend dependencies 54 | run: pnpm install 55 | - name: Build app 56 | uses: tauri-apps/tauri-action@v0 57 | env: 58 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 59 | APPLE_SIGNING_IDENTITY: ${{ secrets.APPLE_SIGNING_IDENTITY }} 60 | APPLE_CERTIFICATE: ${{ secrets.APPLE_CERTIFICATE }} 61 | APPLE_CERTIFICATE_PASSWORD: ${{ secrets.APPLE_CERTIFICATE_PASSWORD }} 62 | APPLE_ID: ${{ secrets.APPLE_ID }} 63 | APPLE_PASSWORD: ${{ secrets.APPLE_PASSWORD }} 64 | APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} 65 | with: 66 | tagName: gitlight-v__VERSION__ 67 | releaseName: 'GitLight v__VERSION__' 68 | releaseBody: 'See the assets to download and install this version.' 69 | releaseDraft: true 70 | prerelease: false 71 | args: ${{ matrix.target && format('--target {0}', matrix.target) }} 72 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | vite.config.js.timestamp-* 10 | vite.config.ts.timestamp-* 11 | .vercel 12 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | engine-strict=true 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | /src-tauri 10 | 11 | # Ignore files for PNPM, NPM and YARN 12 | pnpm-lock.yaml 13 | package-lock.json 14 | yarn.lock 15 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "useTabs": true, 3 | "singleQuote": true, 4 | "trailingComma": "none", 5 | "printWidth": 100, 6 | "plugins": ["prettier-plugin-svelte"], 7 | "overrides": [ 8 | { "files": "*.svelte", "options": { "parser": "svelte" } }, 9 | { "files": "./src/lib/icons/*.svelte", "options": { "htmlWhitespaceSensitivity": "ignore" } } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /.stylelintignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules 3 | /build 4 | /.svelte-kit 5 | /package 6 | .env 7 | .env.* 8 | !.env.example 9 | /src-tauri 10 | 11 | # Ignore files for PNPM, NPM and YARN 12 | pnpm-lock.yaml 13 | package-lock.json 14 | yarn.lock 15 | -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["stylelint-config-standard-scss", "stylelint-config-idiomatic-order"], 3 | "plugins": ["stylelint-prettier"], 4 | "overrides": [ 5 | { 6 | "files": ["*.svelte"], 7 | "extends": "stylelint-config-html/svelte" 8 | } 9 | ], 10 | "rules": { 11 | "color-function-notation": "legacy", 12 | "custom-property-empty-line-before": "never", 13 | "no-descending-specificity": null, 14 | "property-no-vendor-prefix": null, 15 | "selector-pseudo-class-no-unknown": [true, { "ignorePseudoClasses": ["global"] }], 16 | "scss/no-global-function-names": null 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | "recommendations": [ 3 | "svelte.svelte-vscode", 4 | "dbaeumer.vscode-eslint", 5 | "esbenp.prettier-vscode", 6 | "stylelint.vscode-stylelint" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "editor.defaultFormatter": "esbenp.prettier-vscode", 3 | "editor.formatOnSave": true, 4 | "editor.codeActionsOnSave": { 5 | "source.fixAll.eslint": "explicit", 6 | "source.fixAll.stylelint": "explicit" 7 | }, 8 | "eslint": { 9 | "validate": ["svelte"] 10 | }, 11 | "[svelte]": { 12 | "editor.defaultFormatter": "svelte.svelte-vscode" 13 | }, 14 | "svelte.enable-ts-plugin": true, 15 | "stylelint.validate": ["scss", "svelte"] 16 | } 17 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to GitLight 2 | 3 | 👋 Hey, thanks for wanting to improve GitLight! Any contribution is welcome and appreciated! 4 | 5 | --- 6 | 7 | ## Before contributing 8 | 9 | The goal of GitLight is to make developers work faster and stay up to date with their git workflow by providing accurate data, filters and more. It is focused on receiving and managing notifications. I'm trying to make the UI more intuitive and easier to use in order to provide the best possible experience. 10 | 11 | ### Roadmap 12 | 13 | [See the roadmap on GitHub](https://github.com/users/colinlienard/projects/1) 14 | 15 | ### Tech Stack 16 | 17 | - UI → [Svelte](https://svelte.dev/) 18 | - Framework → [SvelteKit](https://kit.svelte.dev/) 19 | - Langage → [Typescript](https://www.typescriptlang.org/) 20 | - Desktop app → [Tauri](https://tauri.app/) 21 | - Deployment → [Vercel](https://vercel.com) 22 | - Package manager → [pnpm](https://pnpm.io/) 23 | 24 | ## How to contribute 25 | 26 | ### Feature request 27 | 28 | If you are using GitLight and are missing a feature that you would find helful, please create an issue. Other may also find it missing. 29 | 30 | ### Reporting bugs 31 | 32 | If you hit a bug, you should first check if it's not already reported in the issues, and if not, please create an issue or contact me on Twitter. 33 | 34 | ### Running locally 35 | 36 | #### Desktop app 37 | 38 | > **Note**: Skip this if you don't want to work on the native app 39 | 40 | Just follow the [Tauri prerequisites](https://tauri.app/v1/guides/getting-started/prerequisites). 41 | 42 | #### GitHub OAuth app 43 | 44 | The app needs to authenticate the user to GitHub, so we need to create a new OAuth GitHub application [here](https://github.com/settings/applications/new). Fill the fields and set the **Authorization callback url** to `http://localhost:5173/auth/github/callback`. 45 | 46 | Also create a unique 32 characters code here: https://generate-secret.vercel.app/32 47 | 48 | Then, create a `.env` file at the root of the project: 49 | 50 | ```.env 51 | AUTH_GITHUB_ID={your client ID} 52 | AUTH_GITHUB_SECRET={your client secret} 53 | AUTH_SECRET={your 32 characters code} 54 | PUBLIC_SITE_URL=http://localhost:5173 55 | ``` 56 | 57 | #### GitLab application 58 | 59 | The app needs to authenticate the user to GitLab, so we need to create a new GitLab application [here](https://gitlab.com/-/profile/applications) and click on **Add new application**. Fill the fields and set the **Callback url** to `http://localhost:5173/auth/gitlab/callback`. Choose the following scopes: 60 | 61 | - `read_api` 62 | - `read_user` 63 | 64 | Also create a unique 32 characters code here: https://generate-secret.vercel.app/32 65 | 66 | Then, create a `.env` file at the root of the project: 67 | 68 | ```.env 69 | AUTH_GITLAB_ID={your client ID} 70 | AUTH_GITLAB_SECRET={your client secret} 71 | AUTH_SECRET={your 32 characters code} 72 | PUBLIC_SITE_URL=http://localhost:5173 73 | ``` 74 | 75 | #### Frontend 76 | 77 | Just install dependencies: 78 | 79 | ```bash 80 | pnpm install 81 | ``` 82 | 83 | Finally, run `pnpm dev` or `pnpm dev:tauri` to start the dev server! 84 | 85 | ## Styleguides 86 | 87 | - PR names should follow the [conventionnal commits](https://www.conventionalcommits.org/en/v1.0.0/) guidelines. 88 | - Code should be valid for Eslint and Prettier. 89 | - In css, `rem` should be used instead of `px` (apart from borders). 90 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Colin Lienard 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, 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, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | 4 | 5 | # GitLight 6 | 7 | GitHub & GitLab notifications on your desktop • [gitlight.app](https://gitlight.app) 8 | 9 | 10 | 11 | 12 | 13 | 18 | 26 | 34 | 39 | 40 | 41 |
Download for 14 | 15 | Windows 16 | 17 | 19 | 20 | 21 | 22 | 23 | Apple Silicon 24 | 25 | 27 | 28 | 29 | 30 | 31 | Mac Intel 32 | 33 | 35 | 36 | Linux 37 | 38 |
42 | 43 |
44 | 45 | 46 | 47 | 48 | 49 | 50 | --- 51 | 52 | ## About 53 | 54 | Better GitHub and/or GitLab notifications. Available on **MacOS**, **Windows**, **Linux** and in the **browser**. Free and open-source. 55 | 56 | You can download the app or install it with Homebrew: 57 | 58 | ```bash 59 | brew install gitlight 60 | ``` 61 | 62 | ## Features 63 | 64 | - Get push notifications 65 | - Monitor notifications with efficiency thanks to a kanban style interface 66 | - Filter by repository, organization, pull request, issues, commits... 67 | - Get precise notification data 68 | - GitHub and GitLab notifications at the same time 69 | - And more... 70 | 71 | ## Contributing 72 | 73 | [How to contribute](./CONTRIBUTING.md) 74 | 75 | ## License 76 | 77 | [MIT](./LICENSE) © Colin Lienard 78 | -------------------------------------------------------------------------------- /assets/apple-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/assets/apple-dark.png -------------------------------------------------------------------------------- /assets/apple-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/assets/apple-light.png -------------------------------------------------------------------------------- /assets/dashboard-dark.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/assets/dashboard-dark.png -------------------------------------------------------------------------------- /assets/dashboard-light.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/assets/dashboard-light.png -------------------------------------------------------------------------------- /assets/linux.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/assets/linux.png -------------------------------------------------------------------------------- /assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/assets/logo.png -------------------------------------------------------------------------------- /assets/windows.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/assets/windows.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gitlight", 3 | "version": "0.17.6", 4 | "private": true, 5 | "type": "module", 6 | "scripts": { 7 | "build": "vite build", 8 | "build:tauri": "APP_ENV=tauri tauri build", 9 | "build:vercel": "APP_ENV=vercel vite build", 10 | "dev": "vite dev", 11 | "dev:tauri": "APP_ENV=tauri tauri dev", 12 | "lint-fix": "prettier --write . && ESLINT_USE_FLAT_CONFIG=false eslint --fix . && stylelint --fix \"src/**/*.{scss,svelte}\"", 13 | "lint:rs": "mkdir build && cd src-tauri && cargo clippy -- -Dwarnings --no-deps; cargo fmt -- --check", 14 | "lint:ts": "prettier --check . && ESLINT_USE_FLAT_CONFIG=false eslint --max-warnings=0 . && stylelint --max-warnings=0 \"src/**/*.{scss,svelte}\"", 15 | "prepare": "svelte-kit sync", 16 | "preview": "vite preview", 17 | "typecheck": "svelte-check --tsconfig ./tsconfig.json" 18 | }, 19 | "dependencies": { 20 | "@rive-app/canvas": "^2.15.6", 21 | "@tauri-apps/api": "^1.5.6", 22 | "overlayscrollbars": "^2.8.0", 23 | "tauri-plugin-autostart-api": "github:tauri-apps/tauri-plugin-autostart", 24 | "worker-timers": "^7.1.8" 25 | }, 26 | "devDependencies": { 27 | "@sveltejs/adapter-static": "^3.0.1", 28 | "@sveltejs/adapter-vercel": "^5.3.0", 29 | "@sveltejs/kit": "^2.5.9", 30 | "@sveltejs/vite-plugin-svelte": "^3.1.0", 31 | "@tauri-apps/cli": "^1.5.14", 32 | "@typescript-eslint/eslint-plugin": "^7.9.0", 33 | "@typescript-eslint/parser": "^7.9.0", 34 | "eslint": "^9.3.0", 35 | "eslint-config-prettier": "^9.1.0", 36 | "eslint-plugin-import": "^2.29.1", 37 | "eslint-plugin-svelte": "^2.39.0", 38 | "prettier": "^3.2.5", 39 | "prettier-plugin-svelte": "^3.2.3", 40 | "sass": "^1.77.2", 41 | "stylelint": "^16.5.0", 42 | "stylelint-config-html": "^1.1.0", 43 | "stylelint-config-idiomatic-order": "^10.0.0", 44 | "stylelint-config-standard-scss": "^13.1.0", 45 | "stylelint-prettier": "^5.0.0", 46 | "svelte": "^4.2.17", 47 | "svelte-check": "^3.7.1", 48 | "tslib": "^2.6.2", 49 | "typescript": "^5.4.5", 50 | "vite": "^5.2.11" 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /src-tauri/.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | /target/ 4 | -------------------------------------------------------------------------------- /src-tauri/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "app" 3 | version = "0.17.6" 4 | description = "A Tauri App" 5 | authors = ["you"] 6 | license = "" 7 | repository = "" 8 | default-run = "app" 9 | edition = "2021" 10 | rust-version = "1.59" 11 | 12 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 13 | 14 | [build-dependencies] 15 | tauri-build = { version = "1.5.2", features = [] } 16 | 17 | [dependencies] 18 | devtools = "0.3.1" 19 | serde_json = "1.0.117" 20 | serde = { version = "1.0.202", features = ["derive"] } 21 | tauri = { version = "1.6.6", features = [ "system-tray", "os-all", "notification-all", "shell-open", "updater", "window-start-dragging", "icon-png"] } 22 | tauri-plugin-autostart = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } 23 | tauri-plugin-deep-link = "0.1.2" 24 | tauri-plugin-positioner = { version = "1.0.5", features = ["system-tray"] } 25 | tauri-plugin-window-state = { git = "https://github.com/tauri-apps/plugins-workspace", branch = "v1" } 26 | time = ">=0.3.35" 27 | 28 | [target.'cfg(target_os = "macos")'.dependencies] 29 | cocoa = "0.25" 30 | objc = "0.2.7" 31 | 32 | [features] 33 | # by default Tauri runs in production mode 34 | # when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL 35 | default = ["custom-protocol"] 36 | # this feature is used for production builds where `devPath` points to the filesystem 37 | # DO NOT remove this 38 | custom-protocol = ["tauri/custom-protocol"] 39 | -------------------------------------------------------------------------------- /src-tauri/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleURLTypes 6 | 7 | 8 | CFBundleURLName 9 | app.gitlight 10 | CFBundleURLSchemes 11 | 12 | gitlight 13 | 14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /src-tauri/build.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | tauri_build::build() 3 | } 4 | -------------------------------------------------------------------------------- /src-tauri/icons/128x128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/128x128.png -------------------------------------------------------------------------------- /src-tauri/icons/128x128@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/128x128@2x.png -------------------------------------------------------------------------------- /src-tauri/icons/32x32.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/32x32.png -------------------------------------------------------------------------------- /src-tauri/icons/Square107x107Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/Square107x107Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square142x142Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/Square142x142Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square150x150Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/Square150x150Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square284x284Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/Square284x284Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square30x30Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/Square30x30Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square310x310Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/Square310x310Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square44x44Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/Square44x44Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square71x71Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/Square71x71Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/Square89x89Logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/Square89x89Logo.png -------------------------------------------------------------------------------- /src-tauri/icons/StoreLogo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/StoreLogo.png -------------------------------------------------------------------------------- /src-tauri/icons/icon.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/icon.icns -------------------------------------------------------------------------------- /src-tauri/icons/icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/icon.ico -------------------------------------------------------------------------------- /src-tauri/icons/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/icon.png -------------------------------------------------------------------------------- /src-tauri/icons/tray-base-macos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/tray-base-macos.png -------------------------------------------------------------------------------- /src-tauri/icons/tray-base.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/tray-base.png -------------------------------------------------------------------------------- /src-tauri/icons/tray-new-macos.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/tray-new-macos.png -------------------------------------------------------------------------------- /src-tauri/icons/tray-new.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/colinlienard/gitlight/231c6bb6729e8532abd4477db6211b6e8f52446a/src-tauri/icons/tray-new.png -------------------------------------------------------------------------------- /src-tauri/src/commands.rs: -------------------------------------------------------------------------------- 1 | use tauri::{CustomMenuItem, SystemTray, SystemTrayMenu, SystemTrayMenuItem}; 2 | 3 | #[tauri::command] 4 | pub fn update_tray(app_handle: tauri::AppHandle, title: Option, new_icon: Option) { 5 | let tray_handle = app_handle.tray_handle_by_id("tray").unwrap(); 6 | #[cfg(target_os = "macos")] 7 | if let Some(title) = title { 8 | tray_handle.set_title(&title).unwrap(); 9 | } 10 | if let Some(new_icon) = new_icon { 11 | if new_icon { 12 | tray_handle.set_icon(get_raw_tray_icon("new")).unwrap(); 13 | } else { 14 | tray_handle.set_icon(get_raw_tray_icon("base")).unwrap(); 15 | } 16 | } 17 | } 18 | 19 | #[tauri::command] 20 | pub fn toggle_tray(app_handle: tauri::AppHandle, show: bool) { 21 | let tray_handle = app_handle.tray_handle_by_id("tray"); 22 | if let Some(tray_handle) = tray_handle { 23 | tray_handle.destroy().unwrap(); 24 | } 25 | if show { 26 | let mut system_tray = SystemTray::new() 27 | .with_id("tray") 28 | .with_icon(get_raw_tray_icon("base")) 29 | .with_menu( 30 | SystemTrayMenu::new() 31 | .add_item(CustomMenuItem::new("dashboard".to_string(), "Dashboard...")) 32 | .add_native_item(SystemTrayMenuItem::Separator) 33 | .add_item(CustomMenuItem::new("quit".to_string(), "Quit")), 34 | ); 35 | #[cfg(target_os = "macos")] 36 | { 37 | system_tray = system_tray 38 | .with_icon_as_template(true) 39 | .with_menu_on_left_click(false) 40 | } 41 | system_tray.build(&app_handle).unwrap(); 42 | } 43 | } 44 | 45 | fn get_raw_tray_icon(image: &str) -> tauri::Icon { 46 | let is_macos = cfg!(target_os = "macos"); 47 | let bytes = match image { 48 | "base" => { 49 | if is_macos { 50 | include_bytes!("../icons/tray-base-macos.png").to_vec() 51 | } else { 52 | include_bytes!("../icons/tray-base.png").to_vec() 53 | } 54 | } 55 | "new" => { 56 | if is_macos { 57 | include_bytes!("../icons/tray-new-macos.png").to_vec() 58 | } else { 59 | include_bytes!("../icons/tray-new.png").to_vec() 60 | } 61 | } 62 | _ => panic!("Unknown tray icon"), 63 | }; 64 | tauri::Icon::Raw(bytes) 65 | } 66 | -------------------------------------------------------------------------------- /src-tauri/src/title_bar.rs: -------------------------------------------------------------------------------- 1 | #[cfg(target_os = "macos")] 2 | use cocoa::appkit::{NSWindow, NSWindowButton}; 3 | use tauri::Window; 4 | 5 | #[cfg(target_os = "macos")] 6 | pub fn hide_window_buttons(window: Window) { 7 | unsafe { 8 | let id = window.ns_window().unwrap() as cocoa::base::id; 9 | let close_button = id.standardWindowButton_(NSWindowButton::NSWindowCloseButton); 10 | let min_button = id.standardWindowButton_(NSWindowButton::NSWindowMiniaturizeButton); 11 | let zoom_button = id.standardWindowButton_(NSWindowButton::NSWindowZoomButton); 12 | let _: () = msg_send![close_button, setHidden: true]; 13 | let _: () = msg_send![min_button, setHidden: true]; 14 | let _: () = msg_send![zoom_button, setHidden: true]; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src-tauri/tauri.conf.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "../node_modules/@tauri-apps/cli/schema.json", 3 | "build": { 4 | "beforeBuildCommand": "pnpm build", 5 | "beforeDevCommand": "pnpm dev", 6 | "devPath": "http://localhost:5173", 7 | "distDir": "../build" 8 | }, 9 | "package": { 10 | "productName": "GitLight", 11 | "version": "0.17.6" 12 | }, 13 | "tauri": { 14 | "allowlist": { 15 | "notification": { 16 | "all": true 17 | }, 18 | "window": { 19 | "startDragging": true 20 | }, 21 | "shell": { 22 | "open": true 23 | }, 24 | "os": { 25 | "all": true 26 | } 27 | }, 28 | "bundle": { 29 | "active": true, 30 | "category": "DeveloperTool", 31 | "copyright": "", 32 | "deb": { 33 | "depends": [] 34 | }, 35 | "externalBin": [], 36 | "icon": [ 37 | "icons/32x32.png", 38 | "icons/128x128.png", 39 | "icons/128x128@2x.png", 40 | "icons/icon.icns", 41 | "icons/icon.ico" 42 | ], 43 | "identifier": "app.gitlight", 44 | "longDescription": "GitHub & GitLab notifications on your desktop", 45 | "macOS": { 46 | "entitlements": null, 47 | "exceptionDomain": "", 48 | "frameworks": [], 49 | "providerShortName": null, 50 | "signingIdentity": null 51 | }, 52 | "resources": [], 53 | "shortDescription": "", 54 | "targets": "all", 55 | "windows": { 56 | "certificateThumbprint": null, 57 | "digestAlgorithm": "sha256", 58 | "timestampUrl": "" 59 | } 60 | }, 61 | "security": { 62 | "csp": null 63 | }, 64 | "updater": { 65 | "active": true, 66 | "endpoints": ["https://gitlight.app/version/{{target}}/{{current_version}}?arch={{arch}}"], 67 | "dialog": true, 68 | "pubkey": "dW50cnVzdGVkIGNvbW1lbnQ6IG1pbmlzaWduIHB1YmxpYyBrZXk6IDFFN0Y4QzExRTAxMkYyRTEKUldUaDhoTGdFWXgvSGdnNWVFSlQ2Qy9iakRld240cVExdy9xWkdWNmMyQlpDZWZFT0pwSU1xNG0K", 69 | "windows": { 70 | "installMode": "passive" 71 | } 72 | }, 73 | "windows": [ 74 | { 75 | "label": "main", 76 | "url": "/dashboard", 77 | "width": 1200, 78 | "height": 800, 79 | "title": "GitLight", 80 | "titleBarStyle": "Overlay", 81 | "hiddenTitle": true 82 | }, 83 | { 84 | "label": "tray", 85 | "url": "/tray", 86 | "width": 400, 87 | "height": 600, 88 | "title": "GitLight", 89 | "titleBarStyle": "Overlay", 90 | "hiddenTitle": true, 91 | "resizable": false, 92 | "visible": false, 93 | "focus": false 94 | } 95 | ], 96 | "systemTray": { 97 | "iconPath": "icons/tray-base.png", 98 | "iconAsTemplate": true, 99 | "menuOnLeftClick": false 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/app.d.ts: -------------------------------------------------------------------------------- 1 | import type { Session } from './lib/types'; 2 | 3 | declare global { 4 | namespace App { 5 | interface Locals { 6 | session?: Session; 7 | } 8 | interface PageData { 9 | session?: Session; 10 | } 11 | } 12 | 13 | interface Window { 14 | __TAURI__: unknown; 15 | } 16 | 17 | const __APP_VERSION__: string; 18 | } 19 | 20 | export {}; 21 | -------------------------------------------------------------------------------- /src/app.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | %sveltekit.head% 8 | 9 | 10 |
%sveltekit.body%
11 | 12 | 37 | 38 | -------------------------------------------------------------------------------- /src/lib/components/common/AnimatedLogo.svelte: -------------------------------------------------------------------------------- 1 | 15 | 16 |
17 | 18 |
19 |
20 | 21 | 39 | -------------------------------------------------------------------------------- /src/lib/components/common/Button.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 | {#if href} 25 | 37 | 38 | 39 | 40 | 41 | {:else} 42 | 59 | {/if} 60 | 61 | 152 | -------------------------------------------------------------------------------- /src/lib/components/common/DragRegion.svelte: -------------------------------------------------------------------------------- 1 |
2 | 3 | 11 | -------------------------------------------------------------------------------- /src/lib/components/common/IconButton.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 17 | 18 | 58 | -------------------------------------------------------------------------------- /src/lib/components/common/InlineSelect.svelte: -------------------------------------------------------------------------------- 1 | 16 | 17 |
18 |

{label}

19 |
    20 | {#each options as option} 21 |
  • 22 | 33 |
  • 34 | {/each} 35 |
  • 40 |
41 |
42 | 43 | 89 | -------------------------------------------------------------------------------- /src/lib/components/common/Input.svelte: -------------------------------------------------------------------------------- 1 | 30 | 31 | 60 | 61 | 126 | -------------------------------------------------------------------------------- /src/lib/components/common/Modal.svelte: -------------------------------------------------------------------------------- 1 | 6 | 7 | 58 | 59 | {#if $$slots.trigger} 60 | 63 | {/if} 64 | 65 |
66 | {#if open} 67 |
86 | 87 | 140 | -------------------------------------------------------------------------------- /src/lib/components/common/ScrollbarContainer.svelte: -------------------------------------------------------------------------------- 1 | 32 | 33 | {#if scroll} 34 |
35 | 36 |
37 | {:else} 38 | 39 | {/if} 40 | 41 | 64 | -------------------------------------------------------------------------------- /src/lib/components/common/Select.svelte: -------------------------------------------------------------------------------- 1 | 21 | 22 |
23 | {#if label} 24 |

{label}

25 | {/if} 26 | 27 | 35 | 36 |
37 | 38 | 89 | -------------------------------------------------------------------------------- /src/lib/components/common/ShrinkableWrapper.svelte: -------------------------------------------------------------------------------- 1 | 23 | 24 |
25 |
26 | 29 | 30 |
31 | {#if !shrinked} 32 |
33 | 34 |
35 | {/if} 36 |
37 | 38 | 75 | -------------------------------------------------------------------------------- /src/lib/components/common/Switch.svelte: -------------------------------------------------------------------------------- 1 | 17 | 18 | 36 | 37 | 119 | -------------------------------------------------------------------------------- /src/lib/components/common/index.ts: -------------------------------------------------------------------------------- 1 | export { default as AnimatedLogo } from './AnimatedLogo.svelte'; 2 | export { default as Button } from './Button.svelte'; 3 | export { default as DragRegion } from './DragRegion.svelte'; 4 | export { default as IconButton } from './IconButton.svelte'; 5 | export { default as InlineSelect } from './InlineSelect.svelte'; 6 | export { default as Input } from './Input.svelte'; 7 | export { default as Modal, modalOpen } from './Modal.svelte'; 8 | export { default as ScrollbarContainer } from './ScrollbarContainer.svelte'; 9 | export { default as Select } from './Select.svelte'; 10 | export { default as ShrinkableWrapper } from './ShrinkableWrapper.svelte'; 11 | export { default as Switch } from './Switch.svelte'; 12 | export { default as Tooltip, type TooltipContent } from './Tooltip.svelte'; 13 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/Banner.svelte: -------------------------------------------------------------------------------- 1 | 76 | 77 | {#if show} 78 | 79 | 88 | 89 | {/if} 90 | 91 | 138 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/LoadingScreen.svelte: -------------------------------------------------------------------------------- 1 | 4 | 5 | 6 |
7 | 8 |
9 |

Loading your data...

10 |

This can take a bit of time.

11 |
12 |
13 |
14 | 15 | 62 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/SyncPill.svelte: -------------------------------------------------------------------------------- 1 | 33 | 34 | {#if $error} 35 | {#if noInternet} 36 |
37 | 38 | No internet 39 |
40 | {:else} 41 | 42 |
43 | 44 | An error occurred 45 |
46 |
47 | {/if} 48 | {:else} 49 |
50 | {#if synced} 51 | 52 | Synced {syncTime}s ago 53 | {:else} 54 | 55 | Syncing... 56 | {/if} 57 |
58 | {/if} 59 | 60 | 113 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/index.ts: -------------------------------------------------------------------------------- 1 | export * from './notifications'; 2 | export * from './priorities'; 3 | export * from './sidebar'; 4 | export { default as Banner } from './Banner.svelte'; 5 | export { default as LoadingScreen } from './LoadingScreen.svelte'; 6 | export { default as Main } from './Main.svelte'; 7 | export { default as SyncPill } from './SyncPill.svelte'; 8 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/notifications/DoneModal.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 | 15 | 19 | 20 |
21 | 22 |
23 | {#if dones.length} 24 |
    25 | {#each dones as notification (notification.id)} 26 |
  • 27 | 28 |
  • 29 | {/each} 30 |
31 | {:else} 32 |
33 |

No notifications to display.

34 |
35 | {/if} 36 |
37 |
38 |
39 | 40 | 67 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/notifications/NotificationDescription.svelte: -------------------------------------------------------------------------------- 1 | 73 | 74 |

82 | {#if prefix} 83 | {prefix} 84 | {/if} 85 | {#if author} 86 | {#if author.avatar} 87 | 95 | {/if} 96 | {#if authorUrl} 97 | 100 | {:else} 101 | {author.login} 102 | {/if} 103 | {/if} 104 | {#each displayDescription as part} 105 | {#if typeof part === 'string'} 106 | {part} 107 | {:else} 108 | {part.text} 109 | {/if} 110 | {/each} 111 |

112 | 113 | 150 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/notifications/NotificationLabels.svelte: -------------------------------------------------------------------------------- 1 | 31 | 32 | {#if labels && labels.length} 33 |
    34 | {#each labels as label} 35 |
  • 36 | {label.name} 37 |
    41 |
  • 42 | {/each} 43 | {#if removed} 44 |
  • 45 | +{removed} 46 |
    47 |
  • 48 | {/if} 49 |
50 | {/if} 51 | 52 | 85 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/notifications/NotificationList.svelte: -------------------------------------------------------------------------------- 1 | 14 | 15 |
    16 | {#if notifications.length} 17 | {#each displayNotifications as notification (notification)} 18 |
  • 19 | 20 |
  • 21 | {/each} 22 | {:else} 23 | 24 | {/if} 25 |
26 | 27 | 37 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/notifications/NotificationPlaceholder.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 |
11 |
12 | 13 |
14 |

No notifications to display

15 | {#if text} 16 |

{text}

17 | {/if} 18 |
19 | 20 | 71 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/notifications/NotificationStatus.svelte: -------------------------------------------------------------------------------- 1 | 24 | 25 |
26 |

{displayTime}

27 | {#if $settings.viewMode === 'List' || isTrayApp} 28 | {#if status === 'pinned'} 29 | 30 | 31 | 32 | {:else if status === 'unread'} 33 |
34 | {/if} 35 | {/if} 36 |
37 | 38 | 71 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/notifications/index.ts: -------------------------------------------------------------------------------- 1 | export { default as DoneModal } from './DoneModal.svelte'; 2 | export { default as Notification } from './Notification.svelte'; 3 | export { default as NotificationColumn } from './NotificationColumn.svelte'; 4 | export { default as NotificationList } from './NotificationList.svelte'; 5 | export { default as NotificationPlaceholder } from './NotificationPlaceholder.svelte'; 6 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/priorities/Priorities.svelte: -------------------------------------------------------------------------------- 1 | 49 | 50 | (editing = false)}> 51 | 55 | 56 | 57 |
58 | 59 |

60 | By enabling priority sorting and specifying priority criterias, you can customize the 61 | importance of notifications and manage them in your own way. 62 |

63 | 64 |
65 | 66 | 67 |
68 | 69 | 70 | {#each priorities as priority} 71 | handleDelete(priority.criteria)} 75 | /> 76 | {/each} 77 | {#if editing} 78 | (editing = false)} /> 79 | {/if} 80 | {#if !priorities.length && !editing} 81 |

No priority criterias yet.

82 | {/if} 83 | 87 |
88 |
89 |
90 | 91 | 110 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/priorities/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Priorities } from './Priorities.svelte'; 2 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/sidebar/SidebarProviders.svelte: -------------------------------------------------------------------------------- 1 | 17 | 18 |
19 | 28 | 37 | 45 |
46 |
47 | 48 | 88 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/sidebar/SidebarSearch.svelte: -------------------------------------------------------------------------------- 1 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/sidebar/SidebarSection.svelte: -------------------------------------------------------------------------------- 1 | 19 | 20 |
21 |
22 |

{title}

23 | 37 | 40 | 41 |
42 |
43 | 44 |
45 |
46 | 47 | 93 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/sidebar/TypeFilters.svelte: -------------------------------------------------------------------------------- 1 | 55 | 56 | settings.update((previous) => ({ ...previous, showOnlyOpen: value })) 65 | } 66 | ]} 67 | first 68 | > 69 | {#each typeFiltersGitlab as { name, type, number, active } (name)} 70 | 75 | {/each} 76 | 77 | 78 | 95 | -------------------------------------------------------------------------------- /src/lib/components/dashboard/sidebar/index.ts: -------------------------------------------------------------------------------- 1 | export { default as Sidebar } from './Sidebar.svelte'; 2 | -------------------------------------------------------------------------------- /src/lib/components/index.ts: -------------------------------------------------------------------------------- 1 | export * from './common'; 2 | export * from './dashboard'; 3 | export * from './landing'; 4 | export * from './login'; 5 | export * from './settings'; 6 | -------------------------------------------------------------------------------- /src/lib/components/landing/DownloadButton.svelte: -------------------------------------------------------------------------------- 1 | 12 | 13 |
(open = !open)} 16 | on:mouseleave={() => (open = false)} 17 | role="presentation" 18 | > 19 | 20 | {#if show && open} 21 |
22 | 26 | 30 | 34 | 38 |
39 | {/if} 40 |
41 | 42 | 76 | -------------------------------------------------------------------------------- /src/lib/components/landing/index.ts: -------------------------------------------------------------------------------- 1 | export { default as DownloadButton } from './DownloadButton.svelte'; 2 | -------------------------------------------------------------------------------- /src/lib/components/login/GithubLoginButton.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 18 | -------------------------------------------------------------------------------- /src/lib/components/login/index.ts: -------------------------------------------------------------------------------- 1 | export { default as GithubLoginButton } from './GithubLoginButton.svelte'; 2 | export { default as GitlabLoginButton } from './GitlabLoginButton.svelte'; 3 | -------------------------------------------------------------------------------- /src/lib/components/settings/App.svelte: -------------------------------------------------------------------------------- 1 | 29 | 30 |
31 | {#if updateAvailable} 32 |

GitLight v{updateAvailable} is available!

33 | 34 | {:else} 35 |

GitLight v{getAppVersion()}

36 | {#if cannotUpdate} 37 | 38 | {:else} 39 | 40 | {/if} 41 | {/if} 42 |
43 | 47 | 48 | 62 | -------------------------------------------------------------------------------- /src/lib/components/settings/accounts/Account.svelte: -------------------------------------------------------------------------------- 1 | 10 | 11 | 36 | 37 | 90 | -------------------------------------------------------------------------------- /src/lib/components/settings/accounts/Accounts.svelte: -------------------------------------------------------------------------------- 1 | 9 | 10 |
    11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 26 | -------------------------------------------------------------------------------- /src/lib/components/settings/accounts/LogOutButton.svelte: -------------------------------------------------------------------------------- 1 | 40 | 41 |