mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-25 18:49:11 +03:00
feat: update dependencies and refactor pullRequestsStore to use RxJS Observable
This commit is contained in:
parent
b4c11c9e6a
commit
94ff6cb3b9
@ -75,6 +75,7 @@
|
|||||||
"prettier-plugin-svelte": "^3.0.3",
|
"prettier-plugin-svelte": "^3.0.3",
|
||||||
"prettier-plugin-tailwindcss": "^0.5.6",
|
"prettier-plugin-tailwindcss": "^0.5.6",
|
||||||
"reflect-metadata": "^0.1.13",
|
"reflect-metadata": "^0.1.13",
|
||||||
|
"rxjs": "^7.8.1",
|
||||||
"svelte": "^4.2.2",
|
"svelte": "^4.2.2",
|
||||||
"svelte-check": "^3.5.2",
|
"svelte-check": "^3.5.2",
|
||||||
"svelte-floating-ui": "^1.5.3",
|
"svelte-floating-ui": "^1.5.3",
|
||||||
|
@ -1,34 +1,41 @@
|
|||||||
import { asyncWritable, type Loadable } from '@square/svelte-store';
|
import type { Loadable } from '@square/svelte-store';
|
||||||
import lscache from 'lscache';
|
import lscache from 'lscache';
|
||||||
|
import { Observable, EMPTY } from 'rxjs';
|
||||||
|
import { switchMap } from 'rxjs/operators';
|
||||||
|
import { storeToObservable } from '$lib/rxjs/store';
|
||||||
|
|
||||||
import { PullRequest, type GitHubIntegrationContext } from '$lib/github/types';
|
import { PullRequest, type GitHubIntegrationContext } from '$lib/github/types';
|
||||||
import { newClient } from '$lib/github/client';
|
import { newClient } from '$lib/github/client';
|
||||||
import type { CustomStore } from '$lib/vbranches/types';
|
|
||||||
|
|
||||||
// Uses the cached value as the initial state and also in the event of being offline
|
// Uses the cached value as the initial state and also in the event of being offline
|
||||||
export function listPullRequestsWithCache(
|
export function listPullRequestsWithCache(
|
||||||
ghContextStore: Loadable<GitHubIntegrationContext | undefined>
|
ghContextStore: Loadable<GitHubIntegrationContext | undefined>
|
||||||
): CustomStore<PullRequest[] | undefined> {
|
): Observable<PullRequest[]> {
|
||||||
const store = asyncWritable(
|
const ghContextObservable = storeToObservable(ghContextStore);
|
||||||
ghContextStore,
|
const prsObservable = ghContextObservable.pipe(
|
||||||
async (ctx, set) => {
|
switchMap((ctx) => {
|
||||||
if (!ctx) return [];
|
if (!ctx) return EMPTY;
|
||||||
|
const obs: Observable<PullRequest[]> = new Observable((observer) => {
|
||||||
const key = ctx.owner + '/' + ctx.repo;
|
const key = ctx.owner + '/' + ctx.repo;
|
||||||
const cachedValue = lscache.get(key);
|
const cachedPrs = lscache.get(key);
|
||||||
if (cachedValue) set(cachedValue);
|
if (cachedPrs) {
|
||||||
const prs = await listPullRequests(ctx);
|
observer.next(cachedPrs);
|
||||||
|
}
|
||||||
|
const request = listPullRequests(ctx);
|
||||||
|
request.then((prs) => {
|
||||||
if (prs) {
|
if (prs) {
|
||||||
|
observer.next(prs);
|
||||||
lscache.set(key, prs, 1440); // 1 day ttl
|
lscache.set(key, prs, 1440); // 1 day ttl
|
||||||
}
|
}
|
||||||
return prs;
|
});
|
||||||
},
|
});
|
||||||
undefined,
|
return obs;
|
||||||
{ trackState: true }
|
})
|
||||||
) as CustomStore<PullRequest[] | undefined>;
|
);
|
||||||
return store;
|
return prsObservable;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function listPullRequests(ctx: GitHubIntegrationContext): Promise<PullRequest[] | undefined> {
|
async function listPullRequests(ctx: GitHubIntegrationContext): Promise<PullRequest[]> {
|
||||||
const octokit = newClient(ctx);
|
const octokit = newClient(ctx);
|
||||||
try {
|
try {
|
||||||
const rsp = await octokit.rest.pulls.list({
|
const rsp = await octokit.rest.pulls.list({
|
||||||
@ -37,7 +44,8 @@ async function listPullRequests(ctx: GitHubIntegrationContext): Promise<PullRequ
|
|||||||
});
|
});
|
||||||
return rsp.data.map(PullRequest.fromApi);
|
return rsp.data.map(PullRequest.fromApi);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.log(e);
|
console.error(e);
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
15
packages/ui/src/lib/rxjs/store.ts
Normal file
15
packages/ui/src/lib/rxjs/store.ts
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
import type { Readable, Writable, Unsubscriber } from 'svelte/store';
|
||||||
|
import { Observable } from 'rxjs';
|
||||||
|
|
||||||
|
export function storeToObservable<T>(svelteStore: Writable<T> | Readable<T>): Observable<T> {
|
||||||
|
let unsubscribe: Unsubscriber;
|
||||||
|
const observable = new Observable<T>((subscriber) => {
|
||||||
|
unsubscribe = svelteStore.subscribe((val) => {
|
||||||
|
subscriber.next(val);
|
||||||
|
});
|
||||||
|
return () => {
|
||||||
|
unsubscribe();
|
||||||
|
};
|
||||||
|
});
|
||||||
|
return observable;
|
||||||
|
}
|
@ -51,7 +51,6 @@ export const load: LayoutLoad = async ({ params }) => {
|
|||||||
const projectStore = getProjectStore(params.projectId);
|
const projectStore = getProjectStore(params.projectId);
|
||||||
|
|
||||||
const pullRequestsStore = listPullRequestsWithCache(githubContextStore);
|
const pullRequestsStore = listPullRequestsWithCache(githubContextStore);
|
||||||
const pullRequestsState = pullRequestsStore.state;
|
|
||||||
|
|
||||||
return {
|
return {
|
||||||
projectId,
|
projectId,
|
||||||
@ -68,7 +67,6 @@ export const load: LayoutLoad = async ({ params }) => {
|
|||||||
remoteBranchState,
|
remoteBranchState,
|
||||||
projectStore,
|
projectStore,
|
||||||
githubContextStore,
|
githubContextStore,
|
||||||
pullRequestsStore,
|
pullRequestsStore
|
||||||
pullRequestsState
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
@ -17,11 +17,12 @@
|
|||||||
import DomainButton from './DomainButton.svelte';
|
import DomainButton from './DomainButton.svelte';
|
||||||
import IconBranch from '$lib/icons/IconBranch.svelte';
|
import IconBranch from '$lib/icons/IconBranch.svelte';
|
||||||
import IconSettings from '$lib/icons/IconSettings.svelte';
|
import IconSettings from '$lib/icons/IconSettings.svelte';
|
||||||
|
import type { Observable } from 'rxjs';
|
||||||
|
|
||||||
export let branchesWithContentStore: CustomStore<Branch[] | undefined>;
|
export let branchesWithContentStore: CustomStore<Branch[] | undefined>;
|
||||||
export let remoteBranchStore: CustomStore<RemoteBranch[] | undefined>;
|
export let remoteBranchStore: CustomStore<RemoteBranch[] | undefined>;
|
||||||
export let baseBranchStore: CustomStore<BaseBranch | undefined>;
|
export let baseBranchStore: CustomStore<BaseBranch | undefined>;
|
||||||
export let pullRequestsStore: CustomStore<PullRequest[] | undefined>;
|
export let pullRequestsStore: Observable<PullRequest[]>;
|
||||||
export let branchController: BranchController;
|
export let branchController: BranchController;
|
||||||
export let project: Project;
|
export let project: Project;
|
||||||
export let githubContext: GitHubIntegrationContext | undefined;
|
export let githubContext: GitHubIntegrationContext | undefined;
|
||||||
|
@ -6,11 +6,10 @@
|
|||||||
import type { PullRequest } from '$lib/github/types';
|
import type { PullRequest } from '$lib/github/types';
|
||||||
import { showMenu } from 'tauri-plugin-context-menu';
|
import { showMenu } from 'tauri-plugin-context-menu';
|
||||||
import { projectPullRequestListingFilter, ListPRsFilter } from '$lib/config/config';
|
import { projectPullRequestListingFilter, ListPRsFilter } from '$lib/config/config';
|
||||||
import type { Loadable } from '@square/svelte-store';
|
import type { Observable } from 'rxjs';
|
||||||
|
|
||||||
export let projectId: string;
|
export let projectId: string;
|
||||||
export let pullRequestsStore: Loadable<PullRequest[] | undefined>;
|
export let pullRequestsStore: Observable<PullRequest[]>;
|
||||||
$: pullRequestsState = pullRequestsStore?.state;
|
|
||||||
|
|
||||||
let rbViewport: HTMLElement;
|
let rbViewport: HTMLElement;
|
||||||
let rbContents: HTMLElement;
|
let rbContents: HTMLElement;
|
||||||
@ -72,11 +71,9 @@
|
|||||||
class="hide-native-scrollbar flex max-h-full flex-grow flex-col overflow-y-scroll overscroll-none"
|
class="hide-native-scrollbar flex max-h-full flex-grow flex-col overflow-y-scroll overscroll-none"
|
||||||
>
|
>
|
||||||
<div bind:this={rbContents}>
|
<div bind:this={rbContents}>
|
||||||
{#if $pullRequestsState?.isLoading}
|
{#if !$pullRequestsStore}
|
||||||
<span>loading...</span>
|
<span>loading...</span>
|
||||||
{:else if $pullRequestsState?.isError}
|
{:else}
|
||||||
<span>something went wrong</span>
|
|
||||||
{:else if $pullRequestsStore}
|
|
||||||
{#each filterPRs($pullRequestsStore, $filterChoice) as pr, i}
|
{#each filterPRs($pullRequestsStore, $filterChoice) as pr, i}
|
||||||
<a
|
<a
|
||||||
href="/{projectId}/pull/{pr.number}"
|
href="/{projectId}/pull/{pr.number}"
|
||||||
|
@ -188,6 +188,9 @@ importers:
|
|||||||
reflect-metadata:
|
reflect-metadata:
|
||||||
specifier: ^0.1.13
|
specifier: ^0.1.13
|
||||||
version: 0.1.13
|
version: 0.1.13
|
||||||
|
rxjs:
|
||||||
|
specifier: ^7.8.1
|
||||||
|
version: 7.8.1
|
||||||
svelte:
|
svelte:
|
||||||
specifier: ^4.2.2
|
specifier: ^4.2.2
|
||||||
version: 4.2.2
|
version: 4.2.2
|
||||||
@ -3857,6 +3860,12 @@ packages:
|
|||||||
queue-microtask: 1.2.3
|
queue-microtask: 1.2.3
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/rxjs@7.8.1:
|
||||||
|
resolution: {integrity: sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==}
|
||||||
|
dependencies:
|
||||||
|
tslib: 2.6.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/sade@1.8.1:
|
/sade@1.8.1:
|
||||||
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
|
resolution: {integrity: sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==}
|
||||||
engines: {node: '>=6'}
|
engines: {node: '>=6'}
|
||||||
|
Loading…
Reference in New Issue
Block a user