mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-12-24 18:12:48 +03:00
merge upstream
This commit is contained in:
commit
f760857e8b
@ -85,11 +85,11 @@ const withLog: FetchMiddleware = (fetch) => async (url, options) => {
|
||||
}
|
||||
};
|
||||
|
||||
export default (
|
||||
export function getCloudApiClient(
|
||||
{ fetch: realFetch }: { fetch: typeof window.fetch } = {
|
||||
fetch: window.fetch
|
||||
}
|
||||
) => {
|
||||
) {
|
||||
const fetch = fetchWith(realFetch, withRequestId, withLog);
|
||||
return {
|
||||
login: {
|
||||
@ -278,4 +278,4 @@ export default (
|
||||
}).then(parseResponseJSON)
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
@ -1,2 +1 @@
|
||||
export { default as Api } from './api';
|
||||
export type { User, LoginToken, Project } from './api';
|
||||
|
@ -20,7 +20,7 @@ export function subscribe(
|
||||
|
||||
const stores: Record<string, WritableLoadable<Activity[]>> = {};
|
||||
|
||||
export function Activities(params: { projectId: string }) {
|
||||
export function getActivitiesStore(params: { projectId: string }) {
|
||||
if (stores[params.projectId]) return stores[params.projectId];
|
||||
|
||||
const store = asyncWritable([], () => list(params));
|
@ -1,6 +1,7 @@
|
||||
import { invoke } from '$lib/ipc';
|
||||
import { asyncWritable, type WritableLoadable } from '@square/svelte-store';
|
||||
import { sessions, git } from '$lib/api';
|
||||
import * as activities from './activities';
|
||||
import * as sessions from '../ipc/sessions';
|
||||
|
||||
const list = (params: { projectId: string; contextLines?: number }) =>
|
||||
invoke<Record<string, string>>('git_wd_diff', {
|
||||
@ -10,10 +11,10 @@ const list = (params: { projectId: string; contextLines?: number }) =>
|
||||
|
||||
const stores: Record<string, WritableLoadable<Record<string, string>>> = {};
|
||||
|
||||
export function Diffs(params: { projectId: string }) {
|
||||
export function getDiffsStore(params: { projectId: string }) {
|
||||
if (stores[params.projectId]) return stores[params.projectId];
|
||||
const store = asyncWritable([], () => list(params));
|
||||
git.activities.subscribe(params, ({ projectId }) => list({ projectId }).then(store.set));
|
||||
activities.subscribe(params, ({ projectId }) => list({ projectId }).then(store.set));
|
||||
sessions.subscribe(params, () => list(params).then(store.set));
|
||||
stores[params.projectId] = store;
|
||||
return store;
|
@ -16,7 +16,7 @@ export function subscribe(
|
||||
|
||||
const stores: Record<string, WritableLoadable<string>> = {};
|
||||
|
||||
export function Head(params: { projectId: string }) {
|
||||
export function getHeadStore(params: { projectId: string }) {
|
||||
if (stores[params.projectId]) return stores[params.projectId];
|
||||
const store = asyncWritable([], () =>
|
||||
get(params).then((head) => head.replace('refs/heads/', ''))
|
@ -1,11 +1,4 @@
|
||||
export * as statuses from './statuses';
|
||||
export { Status } from './statuses';
|
||||
export * as activities from './activities';
|
||||
export type { Activity } from './activities';
|
||||
export * as heads from './heads';
|
||||
export * as diffs from './diffs';
|
||||
export * as indexes from './indexes';
|
||||
export * as fetches from './fetches';
|
||||
|
||||
import { invoke } from '$lib/ipc';
|
||||
|
@ -2,7 +2,7 @@ import { invoke } from '$lib/ipc';
|
||||
import { asyncWritable, type WritableLoadable } from '@square/svelte-store';
|
||||
import * as indexes from './indexes';
|
||||
import * as activities from './activities';
|
||||
import * as sessions from '../sessions';
|
||||
import * as sessions from '../ipc/sessions';
|
||||
|
||||
type FileStatus = 'added' | 'modified' | 'deleted' | 'renamed' | 'typeChange' | 'other';
|
||||
|
||||
@ -11,13 +11,11 @@ export type Status =
|
||||
| { unstaged: FileStatus }
|
||||
| { staged: FileStatus; unstaged: FileStatus };
|
||||
|
||||
export namespace Status {
|
||||
export function isStaged(status: Status): status is { staged: FileStatus } {
|
||||
export function isStaged(status: Status): status is { staged: FileStatus } {
|
||||
return 'staged' in status && status.staged !== null;
|
||||
}
|
||||
export function isUnstaged(status: Status): status is { unstaged: FileStatus } {
|
||||
}
|
||||
export function isUnstaged(status: Status): status is { unstaged: FileStatus } {
|
||||
return 'unstaged' in status && status.unstaged !== null;
|
||||
}
|
||||
}
|
||||
|
||||
export function list(params: { projectId: string }) {
|
||||
@ -26,7 +24,7 @@ export function list(params: { projectId: string }) {
|
||||
|
||||
const stores: Record<string, WritableLoadable<Record<string, Status>>> = {};
|
||||
|
||||
export function Statuses(params: { projectId: string }) {
|
||||
export function getStatusStore(params: { projectId: string }) {
|
||||
if (stores[params.projectId]) return stores[params.projectId];
|
||||
const store = asyncWritable([], () => list(params));
|
||||
sessions.subscribe(params, () => list(params).then(store.set));
|
@ -1,2 +0,0 @@
|
||||
export * from './ipc';
|
||||
export { Api as CloudApi, type User, type LoginToken } from './cloud';
|
@ -5,14 +5,12 @@ export type OperationInsert = { insert: [number, string] };
|
||||
|
||||
export type Operation = OperationDelete | OperationInsert;
|
||||
|
||||
export namespace Operation {
|
||||
export function isDelete(operation: Operation): operation is OperationDelete {
|
||||
export function isDelete(operation: Operation): operation is OperationDelete {
|
||||
return 'delete' in operation;
|
||||
}
|
||||
}
|
||||
|
||||
export function isInsert(operation: Operation): operation is OperationInsert {
|
||||
export function isInsert(operation: Operation): operation is OperationInsert {
|
||||
return 'insert' in operation;
|
||||
}
|
||||
}
|
||||
|
||||
export type Delta = { timestampMs: number; operations: Operation[] };
|
||||
|
@ -1,19 +1,3 @@
|
||||
export * as git from './git';
|
||||
export { Status, type Activity } from './git';
|
||||
export * as deltas from './deltas';
|
||||
export { type Delta, Operation } from './deltas';
|
||||
export * as sessions from './sessions';
|
||||
export { Session } from './sessions';
|
||||
export * as users from './users';
|
||||
export * as projects from './projects';
|
||||
export type { Project } from './projects';
|
||||
export * as searchResults from './search';
|
||||
export { type SearchResult } from './search';
|
||||
export * as files from './files';
|
||||
export * as zip from './zip';
|
||||
export * as bookmarks from './bookmarks';
|
||||
export type { Bookmark } from './bookmarks';
|
||||
|
||||
import { invoke } from '$lib/ipc';
|
||||
|
||||
export function deleteAllData() {
|
||||
|
@ -38,7 +38,7 @@ export function del(params: { id: string }) {
|
||||
|
||||
const store = asyncWritable([], list);
|
||||
|
||||
export function Project({ id }: { id: string }) {
|
||||
export function getProjectStore({ id }: { id: string }) {
|
||||
return {
|
||||
...derived(store, (projects) => projects?.find((p) => p.id === id)),
|
||||
update: (params: Partial<Pick<Project, 'title' | 'description' | 'api'>>) =>
|
||||
@ -56,13 +56,11 @@ export function Project({ id }: { id: string }) {
|
||||
};
|
||||
}
|
||||
|
||||
export function Projects() {
|
||||
return {
|
||||
export const projectsStore = {
|
||||
...store,
|
||||
add: (params: { path: string }) =>
|
||||
add(params).then((project) => {
|
||||
store.update((projects) => [...projects, project]);
|
||||
return project;
|
||||
})
|
||||
};
|
||||
}
|
||||
};
|
||||
|
@ -42,7 +42,8 @@ export function subscribe(
|
||||
|
||||
const stores: Record<string, WritableLoadable<Session[]>> = {};
|
||||
|
||||
export function Sessions(params: { projectId: string }) {
|
||||
// TODO: Figure out why this extra store exists.
|
||||
export function getSessionStore(params: { projectId: string }) {
|
||||
if (params.projectId in stores) return stores[params.projectId];
|
||||
const store = asyncWritable([], () => list(params));
|
||||
|
||||
|
@ -1,11 +1,11 @@
|
||||
import type { User } from '$lib/api';
|
||||
import type { User } from '../cloud/api';
|
||||
import { invoke } from '$lib/ipc';
|
||||
|
||||
export async function get() {
|
||||
return invoke<User | null>('get_user');
|
||||
}
|
||||
|
||||
export function set(params: { user: User }) {
|
||||
export async function set(params: { user: User }) {
|
||||
invoke<void>('set_user', params);
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import tinykeys from 'tinykeys';
|
||||
import type { Project } from '$lib/api';
|
||||
import type { Project } from '$lib/api/ipc/projects';
|
||||
import { derived, readable, writable, type Readable } from '@square/svelte-store';
|
||||
import { Overlay } from '$lib/components';
|
||||
import listAvailableCommands, { Action, type Group } from './commands';
|
||||
|
@ -1,4 +1,5 @@
|
||||
import { type Project, git } from '$lib/api';
|
||||
import type { Project } from '$lib/api/ipc/projects';
|
||||
import { matchFiles } from '$lib/api/git';
|
||||
import { events } from '$lib';
|
||||
import {
|
||||
IconGitCommit,
|
||||
@ -180,7 +181,7 @@ const fileGroup = ({
|
||||
description: 'type part of a file name',
|
||||
commands: []
|
||||
}
|
||||
: git.matchFiles({ projectId: project.id, matchPattern: input }).then((files) => ({
|
||||
: matchFiles({ projectId: project.id, matchPattern: input }).then((files) => ({
|
||||
title: 'Files',
|
||||
description: files.length === 0 ? `no files containing '${input}'` : '',
|
||||
commands: files.map((file) => ({
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { type Delta, Operation } from '$lib/api';
|
||||
import { Differ } from '$lib/components';
|
||||
import { isInsert, type Delta, isDelete } from '$lib/api/ipc/deltas';
|
||||
import Differ from './Differ';
|
||||
import { line } from '$lib/diff';
|
||||
|
||||
export let doc: string;
|
||||
@ -13,12 +13,12 @@
|
||||
const operations = deltas.flatMap((delta) => delta.operations);
|
||||
|
||||
operations.forEach((operation) => {
|
||||
if (Operation.isInsert(operation)) {
|
||||
if (isInsert(operation)) {
|
||||
text =
|
||||
text.slice(0, operation.insert[0]) +
|
||||
operation.insert[1] +
|
||||
text.slice(operation.insert[0]);
|
||||
} else if (Operation.isDelete(operation)) {
|
||||
} else if (isDelete(operation)) {
|
||||
text =
|
||||
text.slice(0, operation.delete[0]) +
|
||||
text.slice(operation.delete[0] + operation.delete[1]);
|
||||
|
@ -1,13 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { type LoginToken, CloudApi } from '$lib/api';
|
||||
import { toasts, stores } from '$lib';
|
||||
import { getCloudApiClient, type LoginToken } from '$lib/api/cloud/api';
|
||||
import { toasts } from '$lib';
|
||||
import { userStore } from '$lib/stores/user';
|
||||
import { derived, writable } from '@square/svelte-store';
|
||||
import { open } from '@tauri-apps/api/shell';
|
||||
import Button from './Button';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
const cloud = CloudApi();
|
||||
const user = stores.user;
|
||||
const cloud = getCloudApiClient();
|
||||
const user = userStore;
|
||||
|
||||
export let width: 'basic' | 'full-width' = 'basic';
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { collapse } from '$lib/paths';
|
||||
import { Status } from '$lib/api';
|
||||
import { isStaged, isUnstaged, type Status } from '$lib/api/git/statuses';
|
||||
|
||||
export let statuses: Record<string, Status>;
|
||||
</script>
|
||||
@ -27,12 +27,12 @@
|
||||
<li class="flex w-full gap-2">
|
||||
<div class="flex w-[3ch] justify-between font-semibold">
|
||||
<span>
|
||||
{#if Status.isStaged(status)}
|
||||
{#if isStaged(status)}
|
||||
{status.staged.slice(0, 1).toUpperCase()}
|
||||
{/if}
|
||||
</span>
|
||||
<span>
|
||||
{#if Status.isUnstaged(status)}
|
||||
{#if isUnstaged(status)}
|
||||
{status.unstaged.slice(0, 1).toUpperCase()}
|
||||
{/if}
|
||||
</span>
|
||||
|
@ -1,4 +1,3 @@
|
||||
export * as api from './api';
|
||||
export * as toasts from './toasts';
|
||||
export { Toaster } from './toasts';
|
||||
export * as week from './week';
|
||||
@ -6,4 +5,3 @@ export * as uisessions from './uisessions';
|
||||
export * as events from './events';
|
||||
export * as hotkeys from './hotkeys';
|
||||
export * as diff from './diff';
|
||||
export * as stores from './stores';
|
||||
|
@ -1,6 +1,6 @@
|
||||
import posthog from 'posthog-js';
|
||||
import { PUBLIC_POSTHOG_API_KEY } from '$env/static/public';
|
||||
import type { User } from '$lib/api';
|
||||
import type { User } from './api/cloud/api';
|
||||
import { getVersion, getName } from '@tauri-apps/api/app';
|
||||
|
||||
interface PostHogClient {
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { setUser } from '@sentry/sveltekit';
|
||||
import type { User } from '$lib/api';
|
||||
import type { User } from './api/cloud/api';
|
||||
|
||||
export default () => {
|
||||
return {
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { writable, type Loadable, derived, Loaded } from 'svelte-loadable-store';
|
||||
import { bookmarks, type Bookmark } from '$lib/api';
|
||||
import * as bookmarks from '$lib/api/ipc/bookmarks';
|
||||
import { get as getValue, type Readable } from '@square/svelte-store';
|
||||
|
||||
const stores: Record<string, Readable<Loadable<Bookmark[]>>> = {};
|
||||
const stores: Record<string, Readable<Loadable<bookmarks.Bookmark[]>>> = {};
|
||||
|
||||
export function list(params: { projectId: string }) {
|
||||
export function getBookmarksStore(params: { projectId: string }) {
|
||||
if (params.projectId in stores) return stores[params.projectId];
|
||||
|
||||
const store = writable(bookmarks.list(params), (set) => {
|
||||
@ -23,11 +23,11 @@ export function list(params: { projectId: string }) {
|
||||
};
|
||||
});
|
||||
stores[params.projectId] = store;
|
||||
return store as Readable<Loadable<Bookmark[]>>;
|
||||
return store as Readable<Loadable<bookmarks.Bookmark[]>>;
|
||||
}
|
||||
|
||||
export function get(params: { projectId: string; timestampMs: number }) {
|
||||
return derived(list({ projectId: params.projectId }), (bookmarks) =>
|
||||
export function getBookmark(params: { projectId: string; timestampMs: number }) {
|
||||
return derived(getBookmarksStore({ projectId: params.projectId }), (bookmarks) =>
|
||||
bookmarks.find((b) => b.timestampMs === params.timestampMs)
|
||||
);
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { writable, type Loadable, Loaded } from 'svelte-loadable-store';
|
||||
import { deltas, type Delta } from '$lib/api';
|
||||
import * as deltas from '$lib/api/ipc/deltas';
|
||||
import { get, type Readable } from '@square/svelte-store';
|
||||
|
||||
const stores: Record<string, Readable<Loadable<Record<string, Delta[]>>>> = {};
|
||||
const stores: Record<string, Readable<Loadable<Record<string, deltas.Delta[]>>>> = {};
|
||||
|
||||
export default (params: { projectId: string; sessionId: string }) => {
|
||||
export function getDeltasStore(params: { projectId: string; sessionId: string }) {
|
||||
const key = `${params.projectId}/${params.sessionId}`;
|
||||
if (key in stores) return stores[key];
|
||||
|
||||
@ -29,5 +29,5 @@ export default (params: { projectId: string; sessionId: string }) => {
|
||||
};
|
||||
});
|
||||
stores[key] = store;
|
||||
return store as Readable<Loadable<Record<string, Delta[]>>>;
|
||||
};
|
||||
return store as Readable<Loadable<Record<string, deltas.Delta[]>>>;
|
||||
}
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { writable, type Loadable, Loaded } from 'svelte-loadable-store';
|
||||
import { files } from '$lib/api';
|
||||
import * as files from '$lib/api/ipc/files';
|
||||
import { get, type Readable } from '@square/svelte-store';
|
||||
|
||||
const stores: Record<string, Readable<Loadable<Record<string, string>>>> = {};
|
||||
|
||||
export default (params: { projectId: string; sessionId: string }) => {
|
||||
export function getFilesStore(params: { projectId: string; sessionId: string }) {
|
||||
const key = `${params.projectId}/${params.sessionId}`;
|
||||
if (key in stores) return stores[key];
|
||||
|
||||
@ -28,4 +28,4 @@ export default (params: { projectId: string; sessionId: string }) => {
|
||||
});
|
||||
stores[key] = store;
|
||||
return store as Readable<Loadable<Record<string, string>>>;
|
||||
};
|
||||
}
|
||||
|
@ -1,5 +0,0 @@
|
||||
export { default as user } from './user';
|
||||
export * as bookmarks from './bookmarks';
|
||||
export { default as deltas } from './deltas';
|
||||
export { default as sessions } from './sessions';
|
||||
export { default as files } from './files';
|
@ -1,10 +1,10 @@
|
||||
import { derived, writable, type Loadable, Loaded } from 'svelte-loadable-store';
|
||||
import { sessions, type Session } from '$lib/api';
|
||||
import * as sessions from '$lib/api/ipc/sessions';
|
||||
import { get, type Readable } from '@square/svelte-store';
|
||||
|
||||
const stores: Record<string, Readable<Loadable<Session[]>>> = {};
|
||||
const stores: Record<string, Readable<Loadable<sessions.Session[]>>> = {};
|
||||
|
||||
export default (params: { projectId: string }) => {
|
||||
export function getSessionStore(params: { projectId: string }) {
|
||||
if (params.projectId in stores) return stores[params.projectId];
|
||||
|
||||
const store = derived(
|
||||
@ -12,7 +12,7 @@ export default (params: { projectId: string }) => {
|
||||
const unsubscribe = sessions.subscribe(params, ({ session }) => {
|
||||
const oldValue = get(store);
|
||||
if (oldValue.isLoading) {
|
||||
sessions.list(params).then(set);
|
||||
sessions.list(params).then((x) => set(x));
|
||||
} else if (Loaded.isError(oldValue)) {
|
||||
sessions.list(params).then(set);
|
||||
} else {
|
||||
@ -33,5 +33,5 @@ export default (params: { projectId: string }) => {
|
||||
(sessions) => sessions.sort((a, b) => a.meta.startTimestampMs - b.meta.startTimestampMs)
|
||||
);
|
||||
stores[params.projectId] = store;
|
||||
return store as Readable<Loadable<Session[]>>;
|
||||
};
|
||||
return store;
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { users } from '$lib/api';
|
||||
import * as users from '$lib/api/ipc/users';
|
||||
import { asyncWritable } from '@square/svelte-store';
|
||||
|
||||
const store = asyncWritable([], users.get, async (user) => {
|
||||
export const userStore = asyncWritable([], users.get, async (user) => {
|
||||
if (user === null) {
|
||||
await users.delete();
|
||||
} else {
|
||||
@ -9,5 +9,3 @@ const store = asyncWritable([], users.get, async (user) => {
|
||||
}
|
||||
return user;
|
||||
});
|
||||
|
||||
export default store;
|
||||
|
@ -1,6 +1,7 @@
|
||||
import { CloudApi } from '$lib/api';
|
||||
import { getCloudApiClient } from './api/cloud/api';
|
||||
import lscache from 'lscache';
|
||||
const cloud = CloudApi();
|
||||
|
||||
const cloud = getCloudApiClient();
|
||||
|
||||
export async function summarizeHunk(diff: string): Promise<string> {
|
||||
const diffHash = hash(diff);
|
||||
|
@ -1,4 +1,5 @@
|
||||
import type { Session, Delta } from '$lib/api';
|
||||
import type { Delta } from './api/ipc/deltas';
|
||||
import type { Session } from './api/ipc/sessions';
|
||||
|
||||
export type UISession = {
|
||||
session: Session;
|
||||
|
@ -1,12 +1,13 @@
|
||||
import { writable, type Loadable, Loaded } from 'svelte-loadable-store';
|
||||
import type { Session, Delta } from '$lib/api';
|
||||
import { Operation } from '$lib/api';
|
||||
import type { Session } from '$lib/api/ipc/sessions';
|
||||
import { getSessionStore } from '$lib/stores/sessions';
|
||||
import type { Readable } from '@square/svelte-store';
|
||||
import { deltas, git } from '$lib/api/ipc';
|
||||
import { stores } from '$lib';
|
||||
import * as fetches from '$lib/api/git/fetches';
|
||||
import * as deltas from '$lib/api/ipc/deltas';
|
||||
import { BaseBranch, Branch, BranchData } from './types';
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
import { invoke } from '$lib/ipc';
|
||||
import { isDelete, isInsert } from '$lib/api/ipc/deltas';
|
||||
|
||||
export interface Refreshable {
|
||||
refresh(): Promise<void | object>;
|
||||
@ -24,7 +25,7 @@ export class BranchStoresCache {
|
||||
}
|
||||
|
||||
const writableStore = writable(listVirtualBranches({ projectId }), (set) => {
|
||||
return stores.sessions({ projectId }).subscribe((sessions) => {
|
||||
return getSessionStore({ projectId }).subscribe((sessions) => {
|
||||
if (sessions.isLoading) return;
|
||||
if (Loaded.isError(sessions)) return;
|
||||
const lastSession = sessions.value.at(-1);
|
||||
@ -70,7 +71,7 @@ export class BranchStoresCache {
|
||||
return cachedStore;
|
||||
}
|
||||
const writableStore = writable(getRemoteBranchesData({ projectId }), (set) => {
|
||||
git.fetches.subscribe({ projectId }, () => {
|
||||
fetches.subscribe({ projectId }, () => {
|
||||
getRemoteBranchesData({ projectId }).then(set);
|
||||
});
|
||||
});
|
||||
@ -91,7 +92,7 @@ export class BranchStoresCache {
|
||||
return cachedStore;
|
||||
}
|
||||
const writableStore = writable(getBaseBranchData({ projectId }), (set) => {
|
||||
git.fetches.subscribe({ projectId }, () => {
|
||||
fetches.subscribe({ projectId }, () => {
|
||||
getBaseBranchData({ projectId }).then(set);
|
||||
});
|
||||
});
|
||||
@ -133,7 +134,7 @@ async function branchesWithFileContent(projectId: string, sessionId: string, bra
|
||||
sessionId: sessionId,
|
||||
paths: filePaths
|
||||
});
|
||||
const sessionDeltas = await invoke<Record<string, Delta[]>>('list_deltas', {
|
||||
const sessionDeltas = await invoke<Record<string, deltas.Delta[]>>('list_deltas', {
|
||||
projectId: projectId,
|
||||
sessionId: sessionId,
|
||||
paths: filePaths
|
||||
@ -141,22 +142,22 @@ async function branchesWithFileContent(projectId: string, sessionId: string, bra
|
||||
const branchesWithContnent = branches.map((branch) => {
|
||||
branch.files.map((file) => {
|
||||
const contentAtSessionStart = sessionFiles[file.path];
|
||||
const deltas = sessionDeltas[file.path];
|
||||
file.content = applyDeltas(contentAtSessionStart, deltas);
|
||||
const ds = sessionDeltas[file.path];
|
||||
file.content = applyDeltas(contentAtSessionStart, ds);
|
||||
});
|
||||
return branch;
|
||||
});
|
||||
return branchesWithContnent;
|
||||
}
|
||||
|
||||
function applyDeltas(text: string, deltas: Delta[]) {
|
||||
if (!deltas) return text;
|
||||
const operations = deltas.flatMap((delta) => delta.operations);
|
||||
function applyDeltas(text: string, ds: deltas.Delta[]) {
|
||||
if (!ds) return text;
|
||||
const operations = ds.flatMap((delta) => delta.operations);
|
||||
operations.forEach((operation) => {
|
||||
if (Operation.isInsert(operation)) {
|
||||
if (isInsert(operation)) {
|
||||
text =
|
||||
text.slice(0, operation.insert[0]) + operation.insert[1] + text.slice(operation.insert[0]);
|
||||
} else if (Operation.isDelete(operation)) {
|
||||
} else if (isDelete(operation)) {
|
||||
text =
|
||||
text.slice(0, operation.delete[0]) + text.slice(operation.delete[0] + operation.delete[1]);
|
||||
}
|
||||
|
@ -1,25 +0,0 @@
|
||||
/**
|
||||
* Virtual Branch feature package (experiment)
|
||||
*
|
||||
* There are three interesting data types coming from the rust IPC api:
|
||||
* - Branch, representing a virtual branch
|
||||
* - BranchData, representing a remote branch
|
||||
* - BaseBranch, representing a target base remote branch
|
||||
*
|
||||
* The three types are obtained as reactive stores from the BranchStoresCache's methods:
|
||||
* - getVirtualBranchStore - List of Branch (virtual branches)
|
||||
* - getRemoteBranchStore - List of BranchData (remote branches)
|
||||
* - getBaseBranchStore - BaseBranch (single target branch)
|
||||
*
|
||||
* BranchController is a class where all virtual branch operations are performed
|
||||
* This class gets the three stores injected at construction so that any related updates can be peformed
|
||||
*
|
||||
* Note to self:
|
||||
*
|
||||
* - Create the BranchStoresCacheat the top level (where projects are listed),
|
||||
* so that it can take advantage of caching, making project navigation quicker.
|
||||
* - Create the BranchController at the level of a specific project and inject it to components that need it.
|
||||
*/
|
||||
export { Branch, File, Hunk, Commit, BranchData, BaseBranch } from './types';
|
||||
export { BranchStoresCache } from './branchStoresCache';
|
||||
export { BranchController } from './branchController';
|
@ -2,7 +2,8 @@
|
||||
import '../styles/main.postcss';
|
||||
|
||||
import { open } from '@tauri-apps/api/dialog';
|
||||
import { toasts, Toaster, events, hotkeys, stores } from '$lib';
|
||||
import { toasts, Toaster, events, hotkeys } from '$lib';
|
||||
import { userStore } from '$lib/stores/user';
|
||||
import type { LayoutData } from './$types';
|
||||
import { Link, Tooltip } from '$lib/components';
|
||||
import { IconEmail } from '$lib/icons';
|
||||
@ -20,7 +21,7 @@
|
||||
export let data: LayoutData;
|
||||
const { posthog, projects, sentry, cloud } = data;
|
||||
|
||||
const user = stores.user;
|
||||
const user = userStore;
|
||||
|
||||
const userSettings = loadUserSettings();
|
||||
initTheme(userSettings);
|
||||
|
@ -1,16 +1,17 @@
|
||||
import type { LayoutLoad } from './$types';
|
||||
import { api } from '$lib';
|
||||
import { getCloudApiClient } from '$lib/api/cloud/api';
|
||||
import { projectsStore } from '$lib/api/ipc/projects';
|
||||
import Posthog from '$lib/posthog';
|
||||
import Sentry from '$lib/sentry';
|
||||
import { BranchStoresCache } from '$lib/vbranches';
|
||||
import { BranchStoresCache } from '$lib/vbranches/branchStoresCache';
|
||||
|
||||
export const ssr = false;
|
||||
export const prerender = false;
|
||||
export const csr = true;
|
||||
|
||||
export const load: LayoutLoad = ({ fetch: realFetch }: { fetch: typeof fetch }) => ({
|
||||
projects: api.projects.Projects(),
|
||||
cloud: api.CloudApi({ fetch: realFetch }),
|
||||
projects: projectsStore,
|
||||
cloud: getCloudApiClient({ fetch: realFetch }),
|
||||
branchStoresCache: new BranchStoresCache(),
|
||||
posthog: Posthog(),
|
||||
sentry: Sentry()
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { Project } from '$lib/api';
|
||||
import type { Project } from '$lib/api/ipc/projects';
|
||||
import { IconHome } from '$lib/icons';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
|
@ -4,28 +4,29 @@
|
||||
import { asyncDerived } from '@square/svelte-store';
|
||||
import { compareDesc, formatDistanceToNow } from 'date-fns';
|
||||
import { IconFolder, IconLoading } from '$lib/icons';
|
||||
import { toasts, api, stores } from '$lib';
|
||||
import type { getCloudApiClient } from '$lib/api/cloud/api';
|
||||
import { userStore } from '$lib/stores/user';
|
||||
import { getProjectStore, projectsStore } from '$lib/api/ipc/projects';
|
||||
import * as toasts from '$lib/toasts';
|
||||
import IconFolderPlus from '$lib/icons/IconFolderPlus.svelte';
|
||||
import { goto } from '$app/navigation';
|
||||
|
||||
export let projects: ReturnType<typeof api.projects.Projects>;
|
||||
export let cloud: ReturnType<typeof api.CloudApi>;
|
||||
export let projects: typeof projectsStore;
|
||||
export let cloud: ReturnType<typeof getCloudApiClient>;
|
||||
|
||||
const user = stores.user;
|
||||
|
||||
const cloudProjects = asyncDerived(user, async (user) =>
|
||||
const cloudProjects = asyncDerived(userStore, async (user) =>
|
||||
user ? await cloud.projects.list(user.access_token) : []
|
||||
);
|
||||
|
||||
let selectedRepositoryId: string | null = null;
|
||||
|
||||
let project: ReturnType<typeof api.projects.Project> | undefined;
|
||||
let project: ReturnType<typeof getProjectStore> | undefined;
|
||||
|
||||
export async function show(id: string) {
|
||||
await user.load();
|
||||
await userStore.load();
|
||||
await cloudProjects.load();
|
||||
if ($user === null) return;
|
||||
project = api.projects.Project({ id });
|
||||
if ($userStore === null) return;
|
||||
project = getProjectStore({ id });
|
||||
modal.show();
|
||||
}
|
||||
|
||||
@ -42,8 +43,8 @@
|
||||
await project
|
||||
.update({ api: { ...existingCloudProject, sync: true } })
|
||||
.then(() => toasts.success(`Project linked`));
|
||||
} else if (selectedRepositoryId === null && $user && project && $project) {
|
||||
const cloudProject = await cloud.projects.create($user?.access_token, {
|
||||
} else if (selectedRepositoryId === null && $userStore && project && $project) {
|
||||
const cloudProject = await cloud.projects.create($userStore?.access_token, {
|
||||
name: $project.title,
|
||||
description: $project.description,
|
||||
uid: $project.id
|
||||
@ -112,7 +113,7 @@
|
||||
</button>
|
||||
{#each $cloudProjects
|
||||
// filter out projects that are already linked
|
||||
.map( (project) => ({ ...project, disabled: $projects?.some((p) => p?.api?.repository_id === project.repository_id) }) )
|
||||
.map( (project) => ({ ...project, disabled: $projectsStore?.some((p) => p?.api?.repository_id === project.repository_id) }) )
|
||||
// sort by last updated
|
||||
.sort((a, b) => compareDesc(new Date(a.updated_at), new Date(b.updated_at)))
|
||||
// sort by name
|
||||
|
@ -1,11 +1,12 @@
|
||||
<script lang="ts">
|
||||
import { toasts, api } from '$lib';
|
||||
import { toasts } from '$lib';
|
||||
import * as zip from '$lib/api/ipc/zip';
|
||||
import { Button, Checkbox, Modal } from '$lib/components';
|
||||
import { page } from '$app/stores';
|
||||
import type { User } from '$lib/api';
|
||||
import type { User, getCloudApiClient } from '$lib/api/cloud/api';
|
||||
|
||||
export let user: User | null;
|
||||
export let cloud: ReturnType<typeof api.CloudApi>;
|
||||
export let cloud: ReturnType<typeof getCloudApiClient>;
|
||||
|
||||
export function show() {
|
||||
modal.show();
|
||||
@ -42,12 +43,12 @@
|
||||
const email = user?.email ?? emailInputValue;
|
||||
toasts.promise(
|
||||
Promise.all([
|
||||
sendLogs ? api.zip.logs().then((path) => readZipFile(path, 'logs.zip')) : undefined,
|
||||
sendLogs ? zip.logs().then((path) => readZipFile(path, 'logs.zip')) : undefined,
|
||||
sendProjectData
|
||||
? api.zip.gitbutlerData({ projectId }).then((path) => readZipFile(path, 'data.zip'))
|
||||
? zip.gitbutlerData({ projectId }).then((path) => readZipFile(path, 'data.zip'))
|
||||
: undefined,
|
||||
sendProjectRepository
|
||||
? api.zip.projectData({ projectId }).then((path) => readZipFile(path, 'project.zip'))
|
||||
? zip.projectData({ projectId }).then((path) => readZipFile(path, 'project.zip'))
|
||||
: undefined
|
||||
]).then(async ([logs, data, repo]) =>
|
||||
cloud.feedback.create(user?.access_token, {
|
||||
|
@ -1,19 +1,22 @@
|
||||
import { api } from '$lib';
|
||||
import { getHeadStore } from '$lib/api/git/heads';
|
||||
import { getStatusStore } from '$lib/api/git/statuses';
|
||||
import { getSessionStore } from '$lib/api/ipc/sessions';
|
||||
import { getDiffsStore } from '$lib/api/git/diffs';
|
||||
import { error } from '@sveltejs/kit';
|
||||
import type { LayoutLoad } from './$types';
|
||||
import type { Loadable } from '@square/svelte-store';
|
||||
import type { Project } from '$lib/api';
|
||||
import { getProjectStore, type Project } from '$lib/api/ipc/projects';
|
||||
|
||||
export const prerender = false;
|
||||
|
||||
export const load: LayoutLoad = async ({ params }) => {
|
||||
const project = api.projects.Project({ id: params.projectId });
|
||||
const project = getProjectStore({ id: params.projectId });
|
||||
if ((await project.load()) === undefined) throw error(404, new Error('Project not found'));
|
||||
return {
|
||||
head: api.git.heads.Head({ projectId: params.projectId }),
|
||||
statuses: api.git.statuses.Statuses({ projectId: params.projectId }),
|
||||
sessions: api.sessions.Sessions({ projectId: params.projectId }),
|
||||
diffs: api.git.diffs.Diffs({ projectId: params.projectId }),
|
||||
head: getHeadStore({ projectId: params.projectId }),
|
||||
statuses: getStatusStore({ projectId: params.projectId }),
|
||||
sessions: getSessionStore({ projectId: params.projectId }),
|
||||
diffs: getDiffsStore({ projectId: params.projectId }),
|
||||
project: project as Loadable<Project> & Pick<typeof project, 'update' | 'delete'>
|
||||
};
|
||||
};
|
||||
|
@ -7,23 +7,24 @@
|
||||
import { Button, Statuses, Tooltip } from '$lib/components';
|
||||
import { goto } from '$app/navigation';
|
||||
import Chat from './Chat.svelte';
|
||||
import { Loaded } from 'svelte-loadable-store';
|
||||
|
||||
export let data: PageData;
|
||||
$: project = derived(data.project, (project) => project);
|
||||
$: statuses = derived(data.statuses, (statuses) => statuses);
|
||||
$: sessions = derived(data.sessions, (sessions) => sessions);
|
||||
$: head = derived(data.head, (head) => head);
|
||||
const { project, statuses, sessions, head } = data;
|
||||
|
||||
$: recentSessions = derived(
|
||||
sessions,
|
||||
(sessions) => {
|
||||
const lastFourDaysOfSessions = sessions?.filter(
|
||||
(session) => session.meta.startTimestampMs >= getTime(subDays(new Date(), 4))
|
||||
(item) => {
|
||||
if (Loaded.isValue(item)) {
|
||||
const lastFourDaysOfSessions = item.value?.filter(
|
||||
(result) => result.meta.startTimestampMs >= getTime(subDays(new Date(), 4))
|
||||
);
|
||||
if (lastFourDaysOfSessions?.length >= 4) return lastFourDaysOfSessions;
|
||||
return sessions
|
||||
return item.value
|
||||
?.slice(0, 4)
|
||||
.sort((a, b) => b.meta.startTimestampMs - a.meta.startTimestampMs);
|
||||
}
|
||||
return [];
|
||||
},
|
||||
[]
|
||||
);
|
||||
|
@ -1,6 +1,6 @@
|
||||
import type { PageLoad } from './$types';
|
||||
import { git } from '$lib/api';
|
||||
import { getActivitiesStore } from '$lib/api/git/activities';
|
||||
|
||||
export const load: PageLoad = async ({ params }) => ({
|
||||
activity: git.activities.Activities({ projectId: params.projectId })
|
||||
activity: getActivitiesStore({ projectId: params.projectId })
|
||||
});
|
||||
|
@ -1,13 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components';
|
||||
import { CloudApi, type Project } from '$lib/api';
|
||||
import { stores } from '$lib';
|
||||
import { getCloudApiClient } from '$lib/api/cloud/api';
|
||||
import { userStore } from '$lib/stores/user';
|
||||
import type { Project } from '$lib/api/ipc/projects';
|
||||
import { marked } from 'marked';
|
||||
import { IconAISparkles } from '$lib/icons';
|
||||
import { onMount } from 'svelte';
|
||||
|
||||
const cloud = CloudApi();
|
||||
const user = stores.user;
|
||||
const cloud = getCloudApiClient();
|
||||
const user = userStore;
|
||||
|
||||
export let project: Project;
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { Delta } from '$lib/api';
|
||||
import type { Delta } from '$lib/api/ipc/deltas';
|
||||
import { fillBuckets, type Bucket } from './histogram';
|
||||
|
||||
export let deltas: Delta[];
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { format, startOfDay } from 'date-fns';
|
||||
import type { Delta } from '$lib/api';
|
||||
import type { Delta } from '$lib/api/ipc/deltas';
|
||||
import { generateBuckets } from './histogram';
|
||||
import { derived, Loaded } from 'svelte-loadable-store';
|
||||
import FileActivity from './FileActivity.svelte';
|
||||
@ -8,13 +8,13 @@
|
||||
import { Link } from '$lib/components';
|
||||
import { IconRewind, IconPlayerPlayFilled, IconLoading, IconSparkle } from '$lib/icons';
|
||||
import { collapse } from '$lib/paths';
|
||||
import type { Session } from '$lib/api';
|
||||
import { stores } from '$lib';
|
||||
import type { Session } from '$lib/api/ipc/sessions';
|
||||
import { getDeltasStore } from '$lib/stores/deltas';
|
||||
|
||||
export let sessions: Session[];
|
||||
|
||||
$: sessionDeltas = (sessions ?? []).map(({ id, projectId }) =>
|
||||
stores.deltas({ sessionId: id, projectId })
|
||||
getDeltasStore({ sessionId: id, projectId })
|
||||
);
|
||||
|
||||
$: deltasByDate = derived(sessionDeltas, (sessionDeltas) =>
|
||||
|
@ -1,6 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { toasts } from '$lib';
|
||||
import { Status, type Project, git, type CloudApi, type User } from '$lib/api';
|
||||
import type { Project } from '$lib/api/ipc/projects';
|
||||
import type { User, getCloudApiClient } from '$lib/api/cloud/api';
|
||||
import { isUnstaged, type Status } from '$lib/api/git/statuses';
|
||||
import { commit, stage } from '$lib/api/git';
|
||||
import { Button, Overlay, Link } from '$lib/components';
|
||||
import { IconGitBranch, IconSparkle } from '$lib/icons';
|
||||
import { Stats } from '$lib/components';
|
||||
@ -14,7 +17,7 @@
|
||||
export let statuses: Record<string, Status>;
|
||||
export let diffs: Record<string, string>;
|
||||
export let user: User;
|
||||
export let cloud: ReturnType<typeof CloudApi>;
|
||||
export let cloud: ReturnType<typeof getCloudApiClient>;
|
||||
|
||||
let summary = '';
|
||||
let description = '';
|
||||
@ -23,10 +26,10 @@
|
||||
|
||||
const stageAll = async () => {
|
||||
const paths = Object.entries(statuses)
|
||||
.filter((entry) => Status.isUnstaged(entry[1]))
|
||||
.filter((entry) => isUnstaged(entry[1]))
|
||||
.map(([path]) => path);
|
||||
if (paths.length === 0) return;
|
||||
await git.stage({
|
||||
await stage({
|
||||
projectId: project.id,
|
||||
paths
|
||||
});
|
||||
@ -66,8 +69,7 @@
|
||||
|
||||
isCommitting = true;
|
||||
await stageAll();
|
||||
git
|
||||
.commit({
|
||||
commit({
|
||||
projectId: project.id,
|
||||
message: description.length > 0 ? `${summary}\n\n${description}` : summary,
|
||||
push: false
|
||||
|
@ -3,13 +3,15 @@
|
||||
import { Button, Checkbox, DiffContext } from '$lib/components';
|
||||
import { collapse } from '$lib/paths';
|
||||
import { derived, writable } from '@square/svelte-store';
|
||||
import { git, Status } from '$lib/api';
|
||||
import { isStaged, isUnstaged } from '$lib/api/git/statuses';
|
||||
import { userStore } from '$lib/stores/user';
|
||||
import { commit, stage, unstage } from '$lib/api/git';
|
||||
import DiffViewer from './DiffViewer.svelte';
|
||||
import { page } from '$app/stores';
|
||||
import { error, success } from '$lib/toasts';
|
||||
import { fly } from 'svelte/transition';
|
||||
import { Modal } from '$lib/components';
|
||||
import { hotkeys, stores } from '$lib';
|
||||
import { hotkeys } from '$lib';
|
||||
import { IconChevronDown, IconChevronUp } from '$lib/icons';
|
||||
import { onMount } from 'svelte';
|
||||
import { unsubscribe } from '$lib/utils';
|
||||
@ -17,19 +19,19 @@
|
||||
export let data: PageData;
|
||||
let { statuses, diffs, cloud, project } = data;
|
||||
|
||||
const user = stores.user;
|
||||
const user = userStore;
|
||||
|
||||
let fullContext = false;
|
||||
let context = 3;
|
||||
|
||||
const stagedFiles = derived(statuses, (statuses) =>
|
||||
Object.entries(statuses ?? {})
|
||||
.filter((status) => Status.isStaged(status[1]))
|
||||
.filter((status) => isStaged(status[1]))
|
||||
.map(([path]) => path)
|
||||
);
|
||||
const unstagedFiles = derived(statuses, (statuses) =>
|
||||
Object.entries(statuses ?? {})
|
||||
.filter((status) => Status.isUnstaged(status[1]))
|
||||
.filter((status) => isUnstaged(status[1]))
|
||||
.map(([path]) => path)
|
||||
);
|
||||
const allFiles = derived(statuses, (statuses) =>
|
||||
@ -97,8 +99,7 @@
|
||||
const description = formData.get('description') as string;
|
||||
|
||||
isCommitting = true;
|
||||
git
|
||||
.commit({
|
||||
commit({
|
||||
projectId: $page.params.projectId,
|
||||
message: description.length > 0 ? `${summary}\n\n${description}` : summary,
|
||||
push: false
|
||||
@ -123,9 +124,7 @@
|
||||
if ($user === null) return;
|
||||
|
||||
const partialDiff = Object.fromEntries(
|
||||
Object.entries($diffs ?? {}).filter(
|
||||
([key]) => $statuses[key] && Status.isStaged($statuses[key])
|
||||
)
|
||||
Object.entries($diffs ?? {}).filter(([key]) => $statuses[key] && isStaged($statuses[key]))
|
||||
);
|
||||
const diff = Object.values(partialDiff).join('\n').slice(0, 5000);
|
||||
|
||||
@ -158,21 +157,17 @@
|
||||
const onGroupCheckboxClick = (e: Event) => {
|
||||
const target = e.target as HTMLInputElement;
|
||||
if (target.checked) {
|
||||
git
|
||||
.stage({
|
||||
stage({
|
||||
projectId: $page.params.projectId,
|
||||
paths: $unstagedFiles
|
||||
})
|
||||
.catch(() => {
|
||||
}).catch(() => {
|
||||
error('Failed to stage files');
|
||||
});
|
||||
} else {
|
||||
git
|
||||
.unstage({
|
||||
unstage({
|
||||
projectId: $page.params.projectId,
|
||||
paths: $stagedFiles
|
||||
})
|
||||
.catch(() => {
|
||||
}).catch(() => {
|
||||
error('Failed to unstage files');
|
||||
});
|
||||
}
|
||||
@ -210,10 +205,10 @@
|
||||
// an git
|
||||
statuses.subscribe((statuses) =>
|
||||
Object.entries(statuses ?? {}).forEach(([file, status]) => {
|
||||
const isStagedAdded = Status.isStaged(status) && status.staged === 'added';
|
||||
const isUnstagedDeleted = Status.isUnstaged(status) && status.unstaged === 'deleted';
|
||||
const isStagedAdded = isStaged(status) && status.staged === 'added';
|
||||
const isUnstagedDeleted = isUnstaged(status) && status.unstaged === 'deleted';
|
||||
if (isStagedAdded && isUnstagedDeleted)
|
||||
git.stage({ projectId: $page.params.projectId, paths: [file] });
|
||||
stage({ projectId: $page.params.projectId, paths: [file] });
|
||||
})
|
||||
);
|
||||
|
||||
@ -288,20 +283,18 @@
|
||||
class="file-changed-item mx-1 mt-1 flex select-text items-center gap-2 rounded bg-card-default px-1 py-1"
|
||||
>
|
||||
<Checkbox
|
||||
checked={Status.isStaged(status)}
|
||||
checked={isStaged(status)}
|
||||
name="path"
|
||||
disabled={isCommitting || isGeneratingCommitMessage}
|
||||
value={path}
|
||||
on:click={() => {
|
||||
Status.isStaged(status)
|
||||
? git
|
||||
.unstage({ projectId: $page.params.projectId, paths: [path] })
|
||||
.catch(() => {
|
||||
isStaged(status)
|
||||
? unstage({ projectId: $page.params.projectId, paths: [path] }).catch(
|
||||
() => {
|
||||
error('Failed to unstage file');
|
||||
})
|
||||
: git
|
||||
.stage({ projectId: $page.params.projectId, paths: [path] })
|
||||
.catch(() => {
|
||||
}
|
||||
)
|
||||
: stage({ projectId: $page.params.projectId, paths: [path] }).catch(() => {
|
||||
error('Failed to stage file');
|
||||
});
|
||||
}}
|
||||
|
@ -1,17 +1,18 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { stores, api } from '$lib';
|
||||
import { getSessionStore } from '$lib/stores/sessions';
|
||||
import * as deltas from '$lib/api/ipc/deltas';
|
||||
import { format } from 'date-fns';
|
||||
import { derived, Loaded } from 'svelte-loadable-store';
|
||||
|
||||
const sessions = stores.sessions({ projectId: $page.params.projectId });
|
||||
const sessions = getSessionStore({ projectId: $page.params.projectId });
|
||||
|
||||
$: fileFilter = $page.url.searchParams.get('file');
|
||||
|
||||
const dates = derived(sessions, async (sessions) => {
|
||||
const sessionDeltas = await Promise.all(
|
||||
sessions.map((session) =>
|
||||
api.deltas.list({
|
||||
deltas.list({
|
||||
projectId: $page.params.projectId,
|
||||
sessionId: session.id,
|
||||
paths: fileFilter ? [fileFilter] : undefined
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { error, redirect } from '@sveltejs/kit';
|
||||
import { format, compareDesc } from 'date-fns';
|
||||
import type { PageLoad } from './$types';
|
||||
import { stores } from '$lib';
|
||||
import { getSessionStore } from '$lib/stores/sessions';
|
||||
import { promisify } from 'svelte-loadable-store';
|
||||
|
||||
export const load: PageLoad = async ({ url, params }) => {
|
||||
const sessions = await promisify(stores.sessions({ projectId: params.projectId }));
|
||||
const sessions = await promisify(getSessionStore({ projectId: params.projectId }));
|
||||
const latestDate = sessions
|
||||
.map((session) => session.meta.startTimestampMs)
|
||||
.sort(compareDesc)
|
||||
|
@ -4,12 +4,16 @@
|
||||
import { derived, Loaded } from 'svelte-loadable-store';
|
||||
import { format } from 'date-fns';
|
||||
import { onMount } from 'svelte';
|
||||
import { api, events, hotkeys, stores } from '$lib';
|
||||
import { events, hotkeys } from '$lib';
|
||||
import BookmarkModal from './BookmarkModal.svelte';
|
||||
import { unsubscribe } from '$lib/utils';
|
||||
import SessionsList from './SessionsList.svelte';
|
||||
import SessionNavigations from './SessionNavigations.svelte';
|
||||
import { IconLoading } from '$lib/icons';
|
||||
import { getSessionStore } from '$lib/stores/sessions';
|
||||
import { getDeltasStore } from '$lib/stores/deltas';
|
||||
import { getFilesStore } from '$lib/stores/files';
|
||||
import * as bookmarks from '$lib/api/ipc/bookmarks';
|
||||
|
||||
export let data: LayoutData;
|
||||
const { currentFilepath, currentTimestamp } = data;
|
||||
@ -17,7 +21,7 @@
|
||||
const filter = derived(page, (page) => page.url.searchParams.get('file'));
|
||||
const projectId = derived(page, (page) => page.params.projectId);
|
||||
|
||||
$: sessions = stores.sessions({ projectId: $page.params.projectId });
|
||||
$: sessions = getSessionStore({ projectId: $page.params.projectId });
|
||||
$: dateSessions = derived([sessions, page], ([sessions, page]) =>
|
||||
sessions
|
||||
.filter((session) => format(session.meta.startTimestampMs, 'yyyy-MM-dd') === page.params.date)
|
||||
@ -27,12 +31,12 @@
|
||||
$: richSessions = derived([dateSessions, projectId, filter], ([sessions, projectId, filter]) =>
|
||||
sessions.map((session) => ({
|
||||
...session,
|
||||
deltas: derived(stores.deltas({ projectId: projectId, sessionId: session.id }), (deltas) =>
|
||||
deltas: derived(getDeltasStore({ projectId: projectId, sessionId: session.id }), (deltas) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(deltas).filter(([path]) => (filter ? path === filter : true))
|
||||
)
|
||||
),
|
||||
files: derived(stores.files({ projectId, sessionId: session.id }), (files) =>
|
||||
files: derived(getFilesStore({ projectId, sessionId: session.id }), (files) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(files).filter(([path]) => (filter ? path === filter : true))
|
||||
)
|
||||
@ -54,7 +58,7 @@
|
||||
events.on('openBookmarkModal', () => bookmarkModal?.show($currentTimestamp)),
|
||||
hotkeys.on('Meta+Shift+D', () => bookmarkModal?.show($currentTimestamp)),
|
||||
hotkeys.on('D', async () => {
|
||||
const existing = await api.bookmarks.list({
|
||||
const existing = await bookmarks.list({
|
||||
projectId: $page.params.projectId,
|
||||
range: {
|
||||
start: $currentTimestamp,
|
||||
@ -73,7 +77,7 @@
|
||||
...existing[0],
|
||||
deleted: !existing[0].deleted
|
||||
};
|
||||
api.bookmarks.upsert(newBookmark);
|
||||
bookmarks.upsert(newBookmark);
|
||||
})
|
||||
)
|
||||
);
|
||||
|
@ -1,11 +1,11 @@
|
||||
import { redirect, error } from '@sveltejs/kit';
|
||||
import { format } from 'date-fns';
|
||||
import type { PageLoad } from './$types';
|
||||
import { stores } from '$lib';
|
||||
import { getSessionStore } from '$lib/stores/sessions';
|
||||
import { promisify } from 'svelte-loadable-store';
|
||||
|
||||
export const load: PageLoad = async ({ params, url }) => {
|
||||
const sessions = await promisify(stores.sessions({ projectId: params.projectId }));
|
||||
const sessions = await promisify(getSessionStore({ projectId: params.projectId }));
|
||||
const dateSessions = sessions.filter(
|
||||
(session) => format(session.meta.startTimestampMs, 'yyyy-MM-dd') === params.date
|
||||
);
|
||||
|
@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { toasts, api } from '$lib';
|
||||
import { toasts } from '$lib';
|
||||
import * as bookmarks from '$lib/api/ipc/bookmarks';
|
||||
import { Button, Modal } from '$lib/components';
|
||||
import { IconBookmarkFilled } from '$lib/icons';
|
||||
|
||||
@ -16,7 +17,7 @@
|
||||
export async function show(ts: number) {
|
||||
reset();
|
||||
timestampMs = ts;
|
||||
const existing = await api.bookmarks.list({
|
||||
const existing = await bookmarks.list({
|
||||
projectId,
|
||||
range: {
|
||||
start: ts,
|
||||
@ -35,7 +36,7 @@
|
||||
Promise.resolve()
|
||||
.then(() => (isCreating = true))
|
||||
.then(() =>
|
||||
api.bookmarks.upsert({
|
||||
bookmarks.upsert({
|
||||
projectId,
|
||||
note,
|
||||
timestampMs: timestampMs ?? Date.now(),
|
||||
|
@ -1,9 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { Operation, type Delta, type Session } from '$lib/api';
|
||||
import type { Session } from '$lib/api/ipc/sessions';
|
||||
import { isInsert, type Delta, isDelete } from '$lib/api/ipc/deltas';
|
||||
import { page } from '$app/stores';
|
||||
import { collapse } from '$lib/paths';
|
||||
import { derived } from '@square/svelte-store';
|
||||
import { stores } from '$lib';
|
||||
import { getBookmarksStore } from '$lib/stores/bookmarks';
|
||||
import { IconBookmarkFilled } from '$lib/icons';
|
||||
import { line } from '$lib/diff';
|
||||
import { Stats } from '$lib/components';
|
||||
@ -19,12 +20,12 @@
|
||||
const operations = deltas.flatMap((delta) => delta.operations);
|
||||
|
||||
operations.forEach((operation) => {
|
||||
if (Operation.isInsert(operation)) {
|
||||
if (isInsert(operation)) {
|
||||
text =
|
||||
text.slice(0, operation.insert[0]) +
|
||||
operation.insert[1] +
|
||||
text.slice(operation.insert[0]);
|
||||
} else if (Operation.isDelete(operation)) {
|
||||
} else if (isDelete(operation)) {
|
||||
text =
|
||||
text.slice(0, operation.delete[0]) +
|
||||
text.slice(operation.delete[0] + operation.delete[1]);
|
||||
@ -51,7 +52,7 @@
|
||||
})
|
||||
.reduce((a, b) => [a[0] + b[0], a[1] + b[1]], [0, 0]);
|
||||
|
||||
$: bookmarks = derived(stores.bookmarks.list({ projectId: session.projectId }), (bookmarks) => {
|
||||
$: bookmarksStore = derived(getBookmarksStore({ projectId: session.projectId }), (bookmarks) => {
|
||||
if (bookmarks.isLoading) return [];
|
||||
if (Loaded.isError(bookmarks)) return [];
|
||||
const timestamps = Object.values(deltas ?? {}).flatMap((deltas) =>
|
||||
@ -110,8 +111,8 @@
|
||||
class:bg-card-active={isCurrent}
|
||||
class="session-card relative rounded border-[0.5px] border-gb-700 text-zinc-300 shadow-md transition-colors duration-200 ease-in-out hover:bg-card-active"
|
||||
>
|
||||
{#await bookmarks.load() then}
|
||||
{#if $bookmarks?.length > 0}
|
||||
{#await bookmarksStore.load() then}
|
||||
{#if $bookmarksStore?.length > 0}
|
||||
<div class="absolute right-5 top-0 flex gap-2 overflow-hidden text-bookmark-selected">
|
||||
<IconBookmarkFilled class="-mt-1 h-4 w-4" />
|
||||
</div>
|
||||
|
@ -4,7 +4,8 @@
|
||||
import { page } from '$app/stores';
|
||||
import { hotkeys } from '$lib';
|
||||
|
||||
import type { Delta, Session } from '$lib/api';
|
||||
import type { Session } from '$lib/api/ipc/sessions';
|
||||
import type { Delta } from '$lib/api/ipc/deltas';
|
||||
import { unsubscribe } from '$lib/utils';
|
||||
import type { Readable } from '@square/svelte-store';
|
||||
import { onMount } from 'svelte';
|
||||
|
@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { Delta, Session } from '$lib/api';
|
||||
import type { Session } from '$lib/api/ipc/sessions';
|
||||
import type { Delta } from '$lib/api/ipc/deltas';
|
||||
import type { Readable } from '@square/svelte-store';
|
||||
import { Loaded, type Loadable } from 'svelte-loadable-store';
|
||||
import { derived } from 'svelte-loadable-store';
|
||||
|
@ -5,12 +5,15 @@
|
||||
import { get, writable } from '@square/svelte-store';
|
||||
import { derived, Loaded } from 'svelte-loadable-store';
|
||||
import { format } from 'date-fns';
|
||||
import { stores } from '$lib';
|
||||
import Playback from './Playback.svelte';
|
||||
import type { Frame as FrameType } from './frame';
|
||||
import Frame from './Frame.svelte';
|
||||
import Info from './Info.svelte';
|
||||
import type { Delta } from '$lib/api';
|
||||
import type { Delta } from '$lib/api/ipc/deltas';
|
||||
import { getSessionStore } from '$lib/stores/sessions';
|
||||
import { getDeltasStore } from '$lib/stores/deltas';
|
||||
import { getFilesStore } from '$lib/stores/files';
|
||||
import { getBookmarksStore } from '$lib/stores/bookmarks';
|
||||
|
||||
export let data: PageData;
|
||||
const { currentFilepath, currentTimestamp, currentSessionId } = data;
|
||||
@ -26,24 +29,23 @@
|
||||
const filter = derived(page, (page) => page.url.searchParams.get('file'));
|
||||
const projectId = derived(page, (page) => page.params.projectId);
|
||||
|
||||
$: bookmarks = stores.bookmarks.list({ projectId: $page.params.projectId });
|
||||
$: sessions = stores.sessions({ projectId: $page.params.projectId });
|
||||
$: dateSessions = derived([sessions, page], ([sessions, page]) =>
|
||||
$: bookmarks = getBookmarksStore({ projectId: $page.params.projectId });
|
||||
$: sessions = getSessionStore({ projectId: $page.params.projectId });
|
||||
$: dateSessions = derived([sessions, page], async ([sessions, page]) =>
|
||||
sessions?.filter(
|
||||
(session) => format(session.meta.startTimestampMs, 'yyyy-MM-dd') === page.params.date
|
||||
)
|
||||
);
|
||||
|
||||
$: richSessions = derived([dateSessions, filter, projectId], ([sessions, filter, projectId]) =>
|
||||
sessions.map((session) => ({
|
||||
...session,
|
||||
deltas: derived(stores.deltas({ projectId: projectId, sessionId: session.id }), (deltas) =>
|
||||
deltas: derived(getDeltasStore({ projectId: projectId, sessionId: session.id }), (deltas) =>
|
||||
Object.entries(deltas)
|
||||
.filter(([path]) => (filter ? path === filter : true))
|
||||
.flatMap(([path, deltas]) => deltas.map((delta) => [path, delta] as [string, Delta]))
|
||||
.sort((a, b) => a[1].timestampMs - b[1].timestampMs)
|
||||
),
|
||||
files: derived(stores.files({ projectId, sessionId: session.id }), (files) =>
|
||||
files: derived(getFilesStore({ projectId, sessionId: session.id }), (files) =>
|
||||
Object.fromEntries(
|
||||
Object.entries(files).filter(([path]) => (filter ? path === filter : true))
|
||||
)
|
||||
|
@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { Delta, Session } from '$lib/api';
|
||||
import type { Session } from '$lib/api/ipc/sessions';
|
||||
import type { Delta } from '$lib/api/ipc/deltas';
|
||||
import type { Frame } from './frame';
|
||||
import { DeltasViewer } from '$lib/components';
|
||||
import type { Readable } from '@square/svelte-store';
|
||||
|
@ -1,20 +1,22 @@
|
||||
<script lang="ts">
|
||||
import { stores, api, events } from '$lib';
|
||||
import { events } from '$lib';
|
||||
import { collapse } from '$lib/paths';
|
||||
import { IconBookmark, IconBookmarkFilled } from '$lib/icons';
|
||||
import { format } from 'date-fns';
|
||||
import { page } from '$app/stores';
|
||||
import { Loaded } from 'svelte-loadable-store';
|
||||
import * as bookmarks from '$lib/api/ipc/bookmarks';
|
||||
import { getBookmark } from '$lib/stores/bookmarks';
|
||||
|
||||
export let timestampMs: number;
|
||||
export let filename: string;
|
||||
|
||||
$: bookmark = stores.bookmarks.get({ projectId: $page.params.projectId, timestampMs });
|
||||
$: bookmark = getBookmark({ projectId: $page.params.projectId, timestampMs });
|
||||
|
||||
const toggleBookmark = () => {
|
||||
if ($bookmark.isLoading) return;
|
||||
if (Loaded.isError($bookmark)) return;
|
||||
api.bookmarks.upsert(
|
||||
bookmarks.upsert(
|
||||
!$bookmark.value
|
||||
? {
|
||||
projectId: $page.params.projectId,
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { Delta } from '$lib/api';
|
||||
import type { Delta } from '$lib/api/ipc/deltas';
|
||||
import { IconPlayerPauseFilled, IconPlayerPlayFilled } from '$lib/icons';
|
||||
import { DiffContext } from '$lib/components';
|
||||
import { unsubscribe } from '$lib/utils';
|
||||
|
@ -1,5 +1,6 @@
|
||||
<script lang="ts">
|
||||
import type { Bookmark, Delta } from '$lib/api';
|
||||
import type { Delta } from '$lib/api/ipc/deltas';
|
||||
import type { Bookmark } from '$lib/api/ipc/bookmarks';
|
||||
import { derived, Loaded, type Loadable } from 'svelte-loadable-store';
|
||||
import type { Readable } from '@square/svelte-store';
|
||||
import { ModuleChapters, ModuleMarkers, type Marker } from './slider';
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { Delta } from '$lib/api';
|
||||
import type { Delta } from '$lib/api/ipc/deltas';
|
||||
|
||||
export type Frame = {
|
||||
sessionId: string;
|
||||
|
@ -1,13 +1,15 @@
|
||||
<script lang="ts">
|
||||
import type { PageData } from './$types';
|
||||
import { IconChevronLeft, IconChevronRight, IconLoading } from '$lib/icons';
|
||||
import { files, deltas, searchResults, type SearchResult } from '$lib/api';
|
||||
import { asyncDerived } from '@square/svelte-store';
|
||||
import { format, formatDistanceToNow } from 'date-fns';
|
||||
import { DeltasViewer } from '$lib/components';
|
||||
import { page } from '$app/stores';
|
||||
import { derived } from '@square/svelte-store';
|
||||
import { goto } from '$app/navigation';
|
||||
import * as search from '$lib/api/ipc/search';
|
||||
import * as files from '$lib/api/ipc/files';
|
||||
import * as deltas from '$lib/api/ipc/deltas';
|
||||
|
||||
export let data: PageData;
|
||||
const { project } = data;
|
||||
@ -19,7 +21,12 @@
|
||||
const openNextPage = () => goto(`?q=${$query}&offset=${$offset + limit}`);
|
||||
const openPrevPage = () => goto(`?q=${$query}&offset=${$offset - limit}`);
|
||||
|
||||
const fetchResultData = async ({ sessionId, projectId, filePath, index }: SearchResult) => {
|
||||
const fetchResultData = async ({
|
||||
sessionId,
|
||||
projectId,
|
||||
filePath,
|
||||
index
|
||||
}: search.SearchResult) => {
|
||||
const [doc, dd] = await Promise.all([
|
||||
files.list({ projectId, sessionId, paths: [filePath] }).then((r) => r[filePath] ?? ''),
|
||||
deltas
|
||||
@ -42,7 +49,7 @@
|
||||
[query, project, offset],
|
||||
async ([query, project, offset]) => {
|
||||
if (!query || !project) return { page: [], total: 0, haveNext: false, havePrev: false };
|
||||
const results = await searchResults.list({ projectId: project.id, query, limit, offset });
|
||||
const results = await search.list({ projectId: project.id, query, limit, offset });
|
||||
return {
|
||||
page: await Promise.all(results.page.map(fetchResultData)),
|
||||
haveNext: offset + limit < results.total,
|
||||
|
@ -3,7 +3,7 @@
|
||||
import ResizeObserver from 'svelte-resize-observer';
|
||||
import setupTerminal from './terminal';
|
||||
import 'xterm/css/xterm.css';
|
||||
import type { Project } from '$lib/api';
|
||||
import type { Project } from '$lib/api/ipc/projects';
|
||||
import { debounce } from '$lib/utils';
|
||||
import { Button, Statuses } from '$lib/components';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { Project } from '$lib/api';
|
||||
import type { Project } from '$lib/api/ipc/projects';
|
||||
import { Terminal } from 'xterm';
|
||||
import { CanvasAddon } from 'xterm-addon-canvas';
|
||||
import { WebglAddon } from 'xterm-addon-webgl';
|
||||
|
@ -3,10 +3,9 @@
|
||||
import Tray from './Tray.svelte';
|
||||
import type { PageData } from './$types';
|
||||
import { Button } from '$lib/components';
|
||||
import { BranchController } from '$lib/vbranches';
|
||||
import { BRANCH_CONTROLLER_KEY, BranchController } from '$lib/vbranches/branchController';
|
||||
import { Loaded } from 'svelte-loadable-store';
|
||||
import { getContext, setContext } from 'svelte';
|
||||
import { BRANCH_CONTROLLER_KEY } from '$lib/vbranches/branchController';
|
||||
import { SETTINGS_CONTEXT, type SettingsStore } from '$lib/userSettings';
|
||||
import BottomPanel from './BottomPanel.svelte';
|
||||
import UpstreamBranchLane from './UpstreamBranchLane.svelte';
|
||||
|
@ -1,7 +1,6 @@
|
||||
import type { PageLoadEvent } from './$types';
|
||||
import { invoke } from '$lib/ipc';
|
||||
import { api } from '$lib';
|
||||
import type { Project } from '$lib/api';
|
||||
import { getProjectStore, type Project } from '$lib/api/ipc/projects';
|
||||
import type { Loadable } from '@square/svelte-store';
|
||||
|
||||
async function getRemoteBranches(params: { projectId: string }) {
|
||||
@ -11,7 +10,7 @@ async function getRemoteBranches(params: { projectId: string }) {
|
||||
export async function load({ parent, params }: PageLoadEvent) {
|
||||
const projectId = params.projectId;
|
||||
const remoteBranchNames = await getRemoteBranches({ projectId });
|
||||
const project = api.projects.Project({ id: params.projectId });
|
||||
const project = getProjectStore({ id: params.projectId });
|
||||
|
||||
const { branchStoresCache } = await parent();
|
||||
const vbranchStore = branchStoresCache.getVirtualBranchStore(projectId);
|
||||
|
@ -1,20 +1,18 @@
|
||||
<script lang="ts" async="true">
|
||||
import Lane from './BranchLane.svelte';
|
||||
import NewBranchDropZone from './NewBranchDropZone.svelte';
|
||||
import type { Branch, BaseBranch } from '$lib/vbranches';
|
||||
import type { BaseBranch, Branch } from '$lib/vbranches/types';
|
||||
import { dzHighlight } from './dropZone';
|
||||
import type { BranchController } from '$lib/vbranches';
|
||||
import { BRANCH_CONTROLLER_KEY, BranchController } from '$lib/vbranches/branchController';
|
||||
import { getContext } from 'svelte';
|
||||
import { BRANCH_CONTROLLER_KEY } from '$lib/vbranches/branchController';
|
||||
import type { CloudApi } from '$lib/api';
|
||||
import type { getCloudApiClient } from '$lib/api/cloud/api';
|
||||
import { Link } from '$lib/components';
|
||||
|
||||
export let projectId: string;
|
||||
export let projectPath: string;
|
||||
export let branches: Branch[];
|
||||
export let base: BaseBranch | undefined;
|
||||
export let cloudEnabled: boolean;
|
||||
export let cloud: ReturnType<typeof CloudApi>;
|
||||
export let cloud: ReturnType<typeof getCloudApiClient>;
|
||||
|
||||
const branchController = getContext<BranchController>(BRANCH_CONTROLLER_KEY);
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { slide } from 'svelte/transition';
|
||||
import { IconTriangleUp, IconTriangleDown } from '$lib/icons';
|
||||
import type { BaseBranch } from '$lib/vbranches';
|
||||
import type { BaseBranch } from '$lib/vbranches/types';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import type { SettingsStore } from '$lib/userSettings';
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { toasts, stores } from '$lib';
|
||||
import type { Commit, File, BaseBranch } from '$lib/vbranches';
|
||||
import { toasts } from '$lib';
|
||||
import { userStore } from '$lib/stores/user';
|
||||
import type { BaseBranch, Commit, File } from '$lib/vbranches/types';
|
||||
import { getContext, onMount } from 'svelte';
|
||||
import { IconAISparkles } from '$lib/icons';
|
||||
import { Button, Link, Tooltip } from '$lib/components';
|
||||
@ -10,15 +11,14 @@
|
||||
import PopupMenu from '../../../lib/components/PopupMenu/PopupMenu.svelte';
|
||||
import PopupMenuItem from '../../../lib/components/PopupMenu/PopupMenuItem.svelte';
|
||||
import { dzHighlight } from './dropZone';
|
||||
import type { BranchController } from '$lib/vbranches';
|
||||
import { BRANCH_CONTROLLER_KEY } from '$lib/vbranches/branchController';
|
||||
import { BRANCH_CONTROLLER_KEY, BranchController } from '$lib/vbranches/branchController';
|
||||
import FileCardNext from './FileCardNext.svelte';
|
||||
import { slide } from 'svelte/transition';
|
||||
import { quintOut } from 'svelte/easing';
|
||||
import { crossfade, fade } from 'svelte/transition';
|
||||
import { flip } from 'svelte/animate';
|
||||
import { invoke } from '@tauri-apps/api/tauri';
|
||||
import type { CloudApi } from '$lib/api';
|
||||
import type { getCloudApiClient } from '$lib/api/cloud/api';
|
||||
import Scrollbar from '$lib/components/Scrollbar.svelte';
|
||||
import IconNewBadge from '$lib/icons/IconNewBadge.svelte';
|
||||
|
||||
@ -50,11 +50,11 @@
|
||||
export let conflicted: boolean;
|
||||
export let base: BaseBranch | undefined;
|
||||
export let cloudEnabled: boolean;
|
||||
export let cloud: ReturnType<typeof CloudApi>;
|
||||
export let cloud: ReturnType<typeof getCloudApiClient>;
|
||||
export let upstream: string | undefined;
|
||||
|
||||
const branchController = getContext<BranchController>(BRANCH_CONTROLLER_KEY);
|
||||
const user = stores.user;
|
||||
const user = userStore;
|
||||
let commitMessage: string;
|
||||
|
||||
$: remoteCommits = commits.filter((c) => c.isRemote);
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import type { Commit } from '$lib/vbranches';
|
||||
import type { Commit } from '$lib/vbranches/types';
|
||||
|
||||
export let commit: Commit;
|
||||
export let url: string | undefined = undefined;
|
||||
|
@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import type { BranchController, Hunk } from '$lib/vbranches';
|
||||
import type { Hunk } from '$lib/vbranches/types';
|
||||
import HunkDiffViewer from './HunkDiffViewer.svelte';
|
||||
import { summarizeHunk } from '$lib/summaries';
|
||||
import { IconTriangleUp, IconTriangleDown } from '$lib/icons';
|
||||
@ -11,7 +11,7 @@
|
||||
import { SETTINGS_CONTEXT, type SettingsStore } from '$lib/userSettings';
|
||||
import { getContext } from 'svelte';
|
||||
import { dzTrigger } from './dropZone';
|
||||
import { BRANCH_CONTROLLER_KEY } from '$lib/vbranches/branchController';
|
||||
import { BRANCH_CONTROLLER_KEY, BranchController } from '$lib/vbranches/branchController';
|
||||
|
||||
const userSettings = getContext<SettingsStore>(SETTINGS_CONTEXT);
|
||||
const branchController = getContext<BranchController>(BRANCH_CONTROLLER_KEY);
|
||||
|
@ -2,7 +2,7 @@
|
||||
import { ContentSection, HunkSection, parseFileSections } from './fileSections';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
import { open } from '@tauri-apps/api/shell';
|
||||
import type { File } from '$lib/vbranches';
|
||||
import type { File } from '$lib/vbranches/types';
|
||||
import RenderedLine from './RenderedLine.svelte';
|
||||
import {
|
||||
IconTriangleUp,
|
||||
@ -11,8 +11,7 @@
|
||||
IconExpandUp,
|
||||
IconExpandDown
|
||||
} from '$lib/icons';
|
||||
import type { BranchController } from '$lib/vbranches';
|
||||
import { BRANCH_CONTROLLER_KEY } from '$lib/vbranches/branchController';
|
||||
import { BRANCH_CONTROLLER_KEY, BranchController } from '$lib/vbranches/branchController';
|
||||
import { getContext } from 'svelte';
|
||||
import { dzTrigger } from './dropZone';
|
||||
import IconExpandUpDownSlim from '$lib/icons/IconExpandUpDownSlim.svelte';
|
||||
|
@ -1,9 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { Button } from '$lib/components';
|
||||
import { dzHighlight } from './dropZone';
|
||||
import type { BranchController } from '$lib/vbranches';
|
||||
import { BRANCH_CONTROLLER_KEY, BranchController } from '$lib/vbranches/branchController';
|
||||
import { getContext } from 'svelte';
|
||||
import { BRANCH_CONTROLLER_KEY } from '$lib/vbranches/branchController';
|
||||
|
||||
const branchController = getContext<BranchController>(BRANCH_CONTROLLER_KEY);
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { Button, Checkbox, Link, Modal } from '$lib/components';
|
||||
import type { Branch, BranchData } from '$lib/vbranches';
|
||||
import type { Branch, BranchData } from '$lib/vbranches/types';
|
||||
import { formatDistanceToNow } from 'date-fns';
|
||||
import { IconGitBranch, IconRemote } from '$lib/icons';
|
||||
import { IconTriangleDown, IconTriangleUp } from '$lib/icons';
|
||||
@ -8,9 +8,8 @@
|
||||
import PopupMenu from '$lib/components/PopupMenu/PopupMenu.svelte';
|
||||
import PopupMenuItem from '$lib/components/PopupMenu/PopupMenuItem.svelte';
|
||||
import { SETTINGS_CONTEXT, type SettingsStore } from '$lib/userSettings';
|
||||
import type { BranchController } from '$lib/vbranches';
|
||||
import { getContext } from 'svelte';
|
||||
import { BRANCH_CONTROLLER_KEY } from '$lib/vbranches/branchController';
|
||||
import { BRANCH_CONTROLLER_KEY, BranchController } from '$lib/vbranches/branchController';
|
||||
import Tooltip from '$lib/components/Tooltip/Tooltip.svelte';
|
||||
import Scrollbar from '$lib/components/Scrollbar.svelte';
|
||||
import IconMeatballMenu from '$lib/icons/IconMeatballMenu.svelte';
|
||||
|
@ -1,10 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { IconBranch, IconRefresh, IconGithub } from '$lib/icons';
|
||||
import { Button, Modal, Tooltip } from '$lib/components';
|
||||
import type { BaseBranch } from '$lib/vbranches';
|
||||
import type { BaseBranch } from '$lib/vbranches/types';
|
||||
import CommitCard from './CommitCard.svelte';
|
||||
import type { BranchController } from '$lib/vbranches';
|
||||
import { BRANCH_CONTROLLER_KEY } from '$lib/vbranches/branchController';
|
||||
import { BRANCH_CONTROLLER_KEY, BranchController } from '$lib/vbranches/branchController';
|
||||
import { getContext } from 'svelte';
|
||||
import Scrollbar from '$lib/components/Scrollbar.svelte';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { File } from '$lib/vbranches';
|
||||
import type { File } from '$lib/vbranches/types';
|
||||
|
||||
const TRUE_KEY = '1';
|
||||
const FALSE_KEY = '0';
|
||||
|
@ -1,5 +1,5 @@
|
||||
import { expect, test } from 'vitest';
|
||||
import type { File, Hunk } from '$lib/vbranches';
|
||||
import type { File, Hunk } from '$lib/vbranches/types';
|
||||
import { parseHunkSection, parseFileSections, SectionType } from './fileSections';
|
||||
import type { ContentSection, HunkSection } from './fileSections';
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
import type { File, Hunk } from '$lib/vbranches';
|
||||
import type { File, Hunk } from '$lib/vbranches/types';
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
|
||||
export type Line = {
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { Branch, File, type Hunk } from '$lib/vbranches';
|
||||
import { Branch, File, type Hunk } from '$lib/vbranches/types';
|
||||
import { plainToInstance } from 'class-transformer';
|
||||
|
||||
let branchCounter = 0;
|
||||
|
@ -1,15 +1,17 @@
|
||||
<script lang="ts">
|
||||
import { Button, Modal } from '$lib/components';
|
||||
import { toasts, api, stores } from '$lib';
|
||||
import { toasts } from '$lib';
|
||||
import { userStore } from '$lib/stores/user';
|
||||
import { goto } from '$app/navigation';
|
||||
import CloudForm from './CloudForm.svelte';
|
||||
import DetailsForm from './DetailsForm.svelte';
|
||||
import type { Project } from '$lib/api';
|
||||
import * as projects from '$lib/api/ipc/projects';
|
||||
import { projectsStore } from '$lib/api/ipc/projects';
|
||||
import type { PageData } from './$types';
|
||||
|
||||
export let data: PageData;
|
||||
const { projects, project, cloud } = data;
|
||||
const user = stores.user;
|
||||
const { project, cloud } = data;
|
||||
const user = userStore;
|
||||
|
||||
let deleteConfirmationModal: Modal;
|
||||
let isDeleting = false;
|
||||
@ -17,19 +19,19 @@
|
||||
const onDeleteClicked = () =>
|
||||
Promise.resolve()
|
||||
.then(() => (isDeleting = true))
|
||||
.then(() => api.projects.del({ id: $project?.id }))
|
||||
.then(() => projects.del({ id: $project?.id }))
|
||||
.then(() => deleteConfirmationModal.close())
|
||||
.catch((e) => {
|
||||
console.error(e);
|
||||
toasts.error('Failed to delete project');
|
||||
})
|
||||
.then(() => goto('/'))
|
||||
.then(() => projects.update((projects) => projects.filter((p) => p.id !== $project?.id)))
|
||||
.then(() => projectsStore.update((projects) => projects.filter((p) => p.id !== $project?.id)))
|
||||
.then(() => toasts.success('Project deleted'))
|
||||
.finally(() => (isDeleting = false));
|
||||
|
||||
const onCloudUpdated = (e: { detail: Project }) => project.update({ ...e.detail });
|
||||
const onDetailsUpdated = async (e: { detail: Project }) => {
|
||||
const onCloudUpdated = (e: { detail: projects.Project }) => project.update({ ...e.detail });
|
||||
const onDetailsUpdated = async (e: { detail: projects.Project }) => {
|
||||
const api =
|
||||
$user && e.detail.api
|
||||
? await cloud.projects.update($user?.access_token, e.detail.api.repository_id, {
|
||||
|
@ -1,7 +1,6 @@
|
||||
import type { PageLoadEvent } from './$types';
|
||||
import { invoke } from '$lib/ipc';
|
||||
import { api } from '$lib';
|
||||
import type { Project } from '$lib/api';
|
||||
import { getProjectStore, type Project } from '$lib/api/ipc/projects';
|
||||
import type { Loadable } from '@square/svelte-store';
|
||||
|
||||
async function getRemoteBranches(params: { projectId: string }) {
|
||||
@ -11,7 +10,7 @@ async function getRemoteBranches(params: { projectId: string }) {
|
||||
export async function load({ parent, params }: PageLoadEvent) {
|
||||
const projectId = params.projectId;
|
||||
const remoteBranchNames = await getRemoteBranches({ projectId });
|
||||
const project = api.projects.Project({ id: params.projectId });
|
||||
const project = getProjectStore({ id: params.projectId });
|
||||
|
||||
const { branchStoresCache } = await parent();
|
||||
const vbranchStore = branchStoresCache.getVirtualBranchStore(projectId);
|
||||
|
@ -1,12 +1,14 @@
|
||||
<script lang="ts">
|
||||
import { stores, toasts } from '$lib';
|
||||
import { CloudApi, type Project } from '$lib/api';
|
||||
import { toasts } from '$lib';
|
||||
import { getCloudApiClient } from '$lib/api/cloud/api';
|
||||
import type { Project } from '$lib/api/ipc/projects';
|
||||
import { userStore } from '$lib/stores/user';
|
||||
import { Login, Checkbox } from '$lib/components';
|
||||
import { createEventDispatcher, onMount } from 'svelte';
|
||||
|
||||
export let project: Project;
|
||||
const user = stores.user;
|
||||
const cloud = CloudApi();
|
||||
const user = userStore;
|
||||
const cloud = getCloudApiClient();
|
||||
|
||||
const dispatch = createEventDispatcher<{
|
||||
updated: Project;
|
||||
|
@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type { Project } from '$lib/api';
|
||||
import type { Project } from '$lib/api/ipc/projects';
|
||||
import { debounce } from '$lib/utils';
|
||||
import { createEventDispatcher } from 'svelte';
|
||||
|
||||
|
@ -1,8 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { Button, Modal, Login, Link } from '$lib/components';
|
||||
import type { PageData } from './$types';
|
||||
import { stores, toasts } from '$lib';
|
||||
import { deleteAllData } from '$lib/api';
|
||||
import { toasts } from '$lib';
|
||||
import { deleteAllData } from '$lib/api/ipc';
|
||||
import { userStore } from '$lib/stores/user';
|
||||
import { goto } from '$app/navigation';
|
||||
import ThemeSelector from '../ThemeSelector.svelte';
|
||||
import { getContext } from 'svelte';
|
||||
@ -13,7 +14,7 @@
|
||||
const { cloud } = data;
|
||||
|
||||
const userSettings = getContext<SettingsStore>(SETTINGS_CONTEXT);
|
||||
const user = stores.user;
|
||||
const user = userStore;
|
||||
|
||||
$: saving = false;
|
||||
|
||||
|
@ -111,7 +111,7 @@ const config = {
|
||||
600: '#C19206',
|
||||
700: '#987105',
|
||||
800: '#6F5004',
|
||||
900: '#713F12',
|
||||
900: '#713F12'
|
||||
},
|
||||
red: {
|
||||
400: '#F87171',
|
||||
@ -142,7 +142,7 @@ const config = {
|
||||
600: '#5852A0',
|
||||
700: '#443D7A',
|
||||
800: '#302854',
|
||||
900: '#1C142E',
|
||||
900: '#1C142E'
|
||||
},
|
||||
orange: {
|
||||
50: '#FEF6E4',
|
||||
@ -154,7 +154,7 @@ const config = {
|
||||
600: '#FA8E4B',
|
||||
700: '#CD6E02',
|
||||
800: '#A55602',
|
||||
900: '#7D3F02',
|
||||
900: '#7D3F02'
|
||||
},
|
||||
zinc: {
|
||||
50: '#fafafa',
|
||||
|
Loading…
Reference in New Issue
Block a user