@kubohiroya/turbowarp-plus-editor-git 0.15.0 → 0.16.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.ja.md +5 -3
- package/README.md +5 -3
- package/dist/close-button.d.ts +6 -0
- package/dist/file-diff-view.d.ts +3 -1
- package/dist/filesystem.d.ts +2 -2
- package/dist/history-graph-view.d.ts +40 -0
- package/dist/history-graph.d.ts +44 -0
- package/dist/index.d.ts +18 -1
- package/dist/index.js +697 -31
- package/dist/local-operations.d.ts +14 -0
- package/dist/messages.d.ts +52 -0
- package/dist/{project-comparison-LAyP_beL.js → project-comparison-1rggIJse.js} +240 -20
- package/dist/project-comparison.d.ts +1 -0
- package/dist/project-source-diff.d.ts +2 -0
- package/dist/project-source-diff.js +2 -2
- package/dist/project-source-review.d.ts +43 -0
- package/dist/project-source-tabs.d.ts +35 -0
- package/dist/pull-request-panel.d.ts +6 -1
- package/dist/{repository-Cx-mxT9l.js → repository-BYno-5f8.js} +491 -4
- package/dist/repository.d.ts +44 -0
- package/dist/repository.js +1 -1
- package/dist/style.css +31 -4
- package/package.json +1 -1
- package/src/close-button.tsx +10 -0
- package/src/file-diff-view.tsx +7 -3
- package/src/filesystem.ts +2 -1
- package/src/history-graph-view.tsx +233 -0
- package/src/history-graph.ts +90 -0
- package/src/index.tsx +137 -17
- package/src/local-operations.ts +59 -4
- package/src/messages.ts +26 -2
- package/src/project-comparison.tsx +4 -2
- package/src/project-source-diff.tsx +2 -0
- package/src/project-source-review.tsx +127 -15
- package/src/project-source-tabs.tsx +118 -0
- package/src/pull-request-panel.tsx +26 -5
- package/src/repository.ts +155 -1
- package/src/style.css +31 -4
|
@@ -13,6 +13,20 @@ export type LocalOperation = {
|
|
|
13
13
|
kind: 'commit';
|
|
14
14
|
message: string;
|
|
15
15
|
author?: GitAuthor;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates `name` at HEAD, at the commit `at`, or at `origin/<name>` with `fromRemote`, and switches to it with
|
|
19
|
+
* `checkout`.
|
|
20
|
+
*/
|
|
21
|
+
| {
|
|
22
|
+
kind: 'createBranch';
|
|
23
|
+
name: string;
|
|
24
|
+
fromRemote?: boolean;
|
|
25
|
+
at?: string;
|
|
26
|
+
checkout: boolean;
|
|
27
|
+
} | {
|
|
28
|
+
kind: 'switchBranch';
|
|
29
|
+
name: string;
|
|
16
30
|
};
|
|
17
31
|
/**
|
|
18
32
|
* Stages, unstages or commits in the granted repository. Like pull, Git's writes are collected first and applied
|
package/dist/messages.d.ts
CHANGED
|
@@ -42,6 +42,10 @@ export declare const messages: {
|
|
|
42
42
|
outdated: string;
|
|
43
43
|
unsupported: string;
|
|
44
44
|
commitMessage: string;
|
|
45
|
+
switchUnsafe: string;
|
|
46
|
+
branchExists: string;
|
|
47
|
+
locked: string;
|
|
48
|
+
branchName: string;
|
|
45
49
|
pullUnsafe: string;
|
|
46
50
|
diverged: string;
|
|
47
51
|
session: string;
|
|
@@ -60,6 +64,16 @@ export declare const messages: {
|
|
|
60
64
|
saveFirst: string;
|
|
61
65
|
author: string;
|
|
62
66
|
nothingStaged: string;
|
|
67
|
+
switchTo: string;
|
|
68
|
+
currentBranch: string;
|
|
69
|
+
createBranch: string;
|
|
70
|
+
newBranch: string;
|
|
71
|
+
switchAfterCreate: string;
|
|
72
|
+
createFromRemote: string;
|
|
73
|
+
remoteBranches: string;
|
|
74
|
+
switched: string;
|
|
75
|
+
branchCreated: string;
|
|
76
|
+
projectMissing: string;
|
|
63
77
|
pulledProject: string;
|
|
64
78
|
confirmPush: string;
|
|
65
79
|
details: string;
|
|
@@ -80,6 +94,18 @@ export declare const messages: {
|
|
|
80
94
|
records: string;
|
|
81
95
|
checkedAt: string;
|
|
82
96
|
failed: string;
|
|
97
|
+
historyMore: string;
|
|
98
|
+
historyLoading: string;
|
|
99
|
+
historyFailed: string;
|
|
100
|
+
historyActions: string;
|
|
101
|
+
historyCreateHere: string;
|
|
102
|
+
historySwitch: string;
|
|
103
|
+
historyCreateFromRemote: string;
|
|
104
|
+
historyCopy: string;
|
|
105
|
+
historyCopied: string;
|
|
106
|
+
historyCopyFailed: string;
|
|
107
|
+
historyRefs: string;
|
|
108
|
+
cancel: string;
|
|
83
109
|
};
|
|
84
110
|
ja: {
|
|
85
111
|
pullRequests: string;
|
|
@@ -124,6 +150,10 @@ export declare const messages: {
|
|
|
124
150
|
outdated: string;
|
|
125
151
|
unsupported: string;
|
|
126
152
|
commitMessage: string;
|
|
153
|
+
switchUnsafe: string;
|
|
154
|
+
branchExists: string;
|
|
155
|
+
locked: string;
|
|
156
|
+
branchName: string;
|
|
127
157
|
pullUnsafe: string;
|
|
128
158
|
diverged: string;
|
|
129
159
|
session: string;
|
|
@@ -142,6 +172,16 @@ export declare const messages: {
|
|
|
142
172
|
saveFirst: string;
|
|
143
173
|
author: string;
|
|
144
174
|
nothingStaged: string;
|
|
175
|
+
switchTo: string;
|
|
176
|
+
currentBranch: string;
|
|
177
|
+
createBranch: string;
|
|
178
|
+
newBranch: string;
|
|
179
|
+
switchAfterCreate: string;
|
|
180
|
+
createFromRemote: string;
|
|
181
|
+
remoteBranches: string;
|
|
182
|
+
switched: string;
|
|
183
|
+
branchCreated: string;
|
|
184
|
+
projectMissing: string;
|
|
145
185
|
pulledProject: string;
|
|
146
186
|
confirmPush: string;
|
|
147
187
|
details: string;
|
|
@@ -162,6 +202,18 @@ export declare const messages: {
|
|
|
162
202
|
records: string;
|
|
163
203
|
checkedAt: string;
|
|
164
204
|
failed: string;
|
|
205
|
+
historyMore: string;
|
|
206
|
+
historyLoading: string;
|
|
207
|
+
historyFailed: string;
|
|
208
|
+
historyActions: string;
|
|
209
|
+
historyCreateHere: string;
|
|
210
|
+
historySwitch: string;
|
|
211
|
+
historyCreateFromRemote: string;
|
|
212
|
+
historyCopy: string;
|
|
213
|
+
historyCopied: string;
|
|
214
|
+
historyCopyFailed: string;
|
|
215
|
+
historyRefs: string;
|
|
216
|
+
cancel: string;
|
|
165
217
|
};
|
|
166
218
|
};
|
|
167
219
|
export type Labels = typeof messages.en;
|
|
@@ -2,6 +2,29 @@ import { n as init_objectSpread2, t as _objectSpread2 } from "./objectSpread2-Dk
|
|
|
2
2
|
import { a as createTwoFilesPatch, i as isAssetName, n as assetsDirectoryParts, o as hasOnlyUnixLineEndings, r as folderSettingsLimit, s as hasOnlyWinLineEndings, t as assetLimit } from "./project-asset-paths-KV715791.js";
|
|
3
3
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
import { render, unmountComponentAtNode } from "react-dom";
|
|
5
|
+
// src/close-button.tsx
|
|
6
|
+
/** A button drawn as an X, named by `label` for screen readers and in its tooltip. */
|
|
7
|
+
function CloseButton({ label, onClick }) {
|
|
8
|
+
return /* @__PURE__ */ React.createElement("button", {
|
|
9
|
+
type: "button",
|
|
10
|
+
className: "twgit-close",
|
|
11
|
+
"aria-label": label,
|
|
12
|
+
title: label,
|
|
13
|
+
onClick
|
|
14
|
+
}, /* @__PURE__ */ React.createElement("svg", {
|
|
15
|
+
viewBox: "0 0 16 16",
|
|
16
|
+
width: "18",
|
|
17
|
+
height: "18",
|
|
18
|
+
"aria-hidden": "true",
|
|
19
|
+
focusable: "false"
|
|
20
|
+
}, /* @__PURE__ */ React.createElement("path", {
|
|
21
|
+
d: "M4 4l8 8M12 4l-8 8",
|
|
22
|
+
stroke: "currentColor",
|
|
23
|
+
strokeWidth: "1.6",
|
|
24
|
+
strokeLinecap: "round",
|
|
25
|
+
fill: "none"
|
|
26
|
+
})));
|
|
27
|
+
}
|
|
5
28
|
// node_modules/diff/libesm/patch/line-endings.js
|
|
6
29
|
function unixToWin(patch) {
|
|
7
30
|
if (Array.isArray(patch)) return patch.map((p) => unixToWin(p));
|
|
@@ -1569,17 +1592,22 @@ function useBlockLocation(comparison, locateBlock) {
|
|
|
1569
1592
|
status: (side) => (location === null || location === void 0 ? void 0 : location.comparison) === comparison && location.locator === locateBlock && location.key === sideKey(side) ? location.status : void 0
|
|
1570
1593
|
};
|
|
1571
1594
|
}
|
|
1572
|
-
|
|
1573
|
-
|
|
1595
|
+
/** What a script is called in a review: its hat block, or both hat blocks when the change replaced it. */
|
|
1596
|
+
function scriptReviewTitle(script, labels) {
|
|
1597
|
+
const beforeTitle = script.before[0] && scriptTitle(script.before[0], labels);
|
|
1598
|
+
const afterTitle = script.after[0] && scriptTitle(script.after[0], labels);
|
|
1599
|
+
return beforeTitle && afterTitle && beforeTitle !== afterTitle ? beforeTitle + " → " + afterTitle : afterTitle !== null && afterTitle !== void 0 ? afterTitle : beforeTitle;
|
|
1600
|
+
}
|
|
1601
|
+
function ScriptComparison({ script, labels, reviewed = false, setReviewed, renderBlock, loadAsset, location, expanded = false }) {
|
|
1602
|
+
const [open, setOpen] = useState(expanded);
|
|
1574
1603
|
const { sync, toggle } = usePreviewSync(labels === ja ? "ja" : "en");
|
|
1575
1604
|
const status = script.kind;
|
|
1576
1605
|
const locale = labels === ja ? "ja" : "en";
|
|
1577
1606
|
const summary = script.summary.map((item) => summaryPhrase(item, locale)).join(labels === ja ? "、" : ", ");
|
|
1578
|
-
const
|
|
1579
|
-
const afterTitle = script.after[0] && scriptTitle(script.after[0], labels);
|
|
1580
|
-
const title = beforeTitle && afterTitle && beforeTitle !== afterTitle ? beforeTitle + " → " + afterTitle : afterTitle !== null && afterTitle !== void 0 ? afterTitle : beforeTitle;
|
|
1607
|
+
const title = scriptReviewTitle(script, labels);
|
|
1581
1608
|
return /* @__PURE__ */ React.createElement("details", {
|
|
1582
1609
|
className: "twgit-review-script",
|
|
1610
|
+
open: expanded || void 0,
|
|
1583
1611
|
onToggle: (event) => setOpen(event.currentTarget.open)
|
|
1584
1612
|
}, /* @__PURE__ */ React.createElement("summary", null, /* @__PURE__ */ React.createElement("span", { className: "twgit-review-status" }, labels[status]), /* @__PURE__ */ React.createElement("strong", null, title), status === "reorganized" && /* @__PURE__ */ React.createElement("small", null, script.before.length, " → ", script.after.length), summary && /* @__PURE__ */ React.createElement("small", { className: "twgit-review-summary" }, summary), reviewed && /* @__PURE__ */ React.createElement("small", null, labels.reviewed)), open && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "twgit-block-diff-sides" }, ["before", "after"].map((version) => /* @__PURE__ */ React.createElement("div", { key: version }, script[version].length ? script[version].map((side, index, sides) => /* @__PURE__ */ React.createElement(BlockPreview, {
|
|
1585
1613
|
key: side.id,
|
|
@@ -1781,7 +1809,20 @@ var scriptPrint = (script) => fingerprint([
|
|
|
1781
1809
|
script.after.map(scriptBlocks)
|
|
1782
1810
|
]);
|
|
1783
1811
|
var storageKey = (name) => `turbowarp-plus-git:reviewed:${name}`;
|
|
1784
|
-
var
|
|
1812
|
+
var memoryMarks = /* @__PURE__ */ new Map();
|
|
1813
|
+
var markListeners = /* @__PURE__ */ new Map();
|
|
1814
|
+
var subscribeMarks = (name, listener) => {
|
|
1815
|
+
var _markListeners$get;
|
|
1816
|
+
const listeners = (_markListeners$get = markListeners.get(name)) !== null && _markListeners$get !== void 0 ? _markListeners$get : /* @__PURE__ */ new Set();
|
|
1817
|
+
markListeners.set(name, listeners.add(listener));
|
|
1818
|
+
return () => {
|
|
1819
|
+
listeners.delete(listener);
|
|
1820
|
+
if (!listeners.size) markListeners.delete(name);
|
|
1821
|
+
};
|
|
1822
|
+
};
|
|
1823
|
+
var readMarks = (name, remember = true) => {
|
|
1824
|
+
var _memoryMarks$get;
|
|
1825
|
+
if (!remember) return (_memoryMarks$get = memoryMarks.get(name)) !== null && _memoryMarks$get !== void 0 ? _memoryMarks$get : {};
|
|
1785
1826
|
try {
|
|
1786
1827
|
var _globalThis$localStor, _globalThis$localStor2;
|
|
1787
1828
|
const value = JSON.parse((_globalThis$localStor = (_globalThis$localStor2 = globalThis.localStorage) === null || _globalThis$localStor2 === void 0 ? void 0 : _globalThis$localStor2.getItem(storageKey(name))) !== null && _globalThis$localStor !== void 0 ? _globalThis$localStor : "{}");
|
|
@@ -1790,12 +1831,18 @@ var readMarks = (name) => {
|
|
|
1790
1831
|
return {};
|
|
1791
1832
|
}
|
|
1792
1833
|
};
|
|
1793
|
-
var writeMarks = (name, marks) => {
|
|
1834
|
+
var writeMarks = (name, marks, remember = true) => {
|
|
1835
|
+
var _markListeners$get2;
|
|
1836
|
+
if (!remember) {
|
|
1837
|
+
if (Object.keys(marks).length) memoryMarks.set(name, marks);
|
|
1838
|
+
else memoryMarks.delete(name);
|
|
1839
|
+
}
|
|
1794
1840
|
try {
|
|
1795
1841
|
var _globalThis$localStor3, _globalThis$localStor4;
|
|
1796
|
-
if (Object.keys(marks).length) (_globalThis$localStor3 = globalThis.localStorage) === null || _globalThis$localStor3 === void 0 || _globalThis$localStor3.setItem(storageKey(name), JSON.stringify(marks));
|
|
1797
|
-
else (_globalThis$localStor4 = globalThis.localStorage) === null || _globalThis$localStor4 === void 0 || _globalThis$localStor4.removeItem(storageKey(name));
|
|
1842
|
+
if (remember && Object.keys(marks).length) (_globalThis$localStor3 = globalThis.localStorage) === null || _globalThis$localStor3 === void 0 || _globalThis$localStor3.setItem(storageKey(name), JSON.stringify(marks));
|
|
1843
|
+
else if (remember) (_globalThis$localStor4 = globalThis.localStorage) === null || _globalThis$localStor4 === void 0 || _globalThis$localStor4.removeItem(storageKey(name));
|
|
1798
1844
|
} catch (_unused4) {}
|
|
1845
|
+
(_markListeners$get2 = markListeners.get(name)) === null || _markListeners$get2 === void 0 || _markListeners$get2.forEach((listener) => listener());
|
|
1799
1846
|
};
|
|
1800
1847
|
function ProjectSourceReview({ title, description, verification, files, renderBlock, locale = "en", rememberAs }) {
|
|
1801
1848
|
const labels = locale.startsWith("ja") ? ja : en;
|
|
@@ -1826,20 +1873,24 @@ function ProjectSourceReview({ title, description, verification, files, renderBl
|
|
|
1826
1873
|
return prints;
|
|
1827
1874
|
}, [entries]);
|
|
1828
1875
|
const [checked, setChecked] = useState();
|
|
1876
|
+
const [, refresh] = useState(0);
|
|
1877
|
+
useEffect(() => rememberAs ? subscribeMarks(rememberAs, () => {
|
|
1878
|
+
setChecked(void 0);
|
|
1879
|
+
refresh((count) => count + 1);
|
|
1880
|
+
}) : void 0, [rememberAs]);
|
|
1829
1881
|
const marks = (checked === null || checked === void 0 ? void 0 : checked.entries) === entries ? checked.marks : rememberAs ? readMarks(rememberAs) : {};
|
|
1830
1882
|
const reviewed = new Set([...scriptPrints].filter(([key, print]) => marks[key] === print).map(([key]) => key));
|
|
1831
|
-
const setReviewed = (key, value) =>
|
|
1832
|
-
const current = (previous === null || previous === void 0 ? void 0 : previous.entries) === entries ? previous.marks : rememberAs ? readMarks(rememberAs) : {};
|
|
1883
|
+
const setReviewed = (key, value) => {
|
|
1833
1884
|
const next = {};
|
|
1834
|
-
for (const [name, print] of scriptPrints) if (
|
|
1885
|
+
for (const [name, print] of scriptPrints) if (marks[name] === print) next[name] = print;
|
|
1835
1886
|
if (value) next[key] = scriptPrints.get(key);
|
|
1836
1887
|
else delete next[key];
|
|
1837
1888
|
if (rememberAs) writeMarks(rememberAs, next);
|
|
1838
|
-
|
|
1889
|
+
setChecked({
|
|
1839
1890
|
entries,
|
|
1840
1891
|
marks: next
|
|
1841
|
-
};
|
|
1842
|
-
}
|
|
1892
|
+
});
|
|
1893
|
+
};
|
|
1843
1894
|
const targets = entries.reduce((total, entry) => {
|
|
1844
1895
|
var _entry$comparison$tar, _entry$comparison;
|
|
1845
1896
|
return total + ((_entry$comparison$tar = (_entry$comparison = entry.comparison) === null || _entry$comparison === void 0 ? void 0 : _entry$comparison.targets.length) !== null && _entry$comparison$tar !== void 0 ? _entry$comparison$tar : 0);
|
|
@@ -1871,6 +1922,62 @@ function ProjectSourceReview({ title, description, verification, files, renderBl
|
|
|
1871
1922
|
}
|
|
1872
1923
|
}))));
|
|
1873
1924
|
}
|
|
1925
|
+
/** The words of one tab of a project comparison opened as tabs. */
|
|
1926
|
+
function reviewTabWords(locale) {
|
|
1927
|
+
const labels = locale.startsWith("ja") ? ja : en;
|
|
1928
|
+
return {
|
|
1929
|
+
script: (script) => `${scriptReviewTitle(script, labels)} · ${labels[script.kind]}`,
|
|
1930
|
+
target: (target) => target.isStage ? labels.stage : target.name,
|
|
1931
|
+
targetDetails: labels.properties,
|
|
1932
|
+
project: labels.comparison,
|
|
1933
|
+
noChanges: labels.noChanges
|
|
1934
|
+
};
|
|
1935
|
+
}
|
|
1936
|
+
function useReviewMark(place, script) {
|
|
1937
|
+
const [, refresh] = useState(0);
|
|
1938
|
+
useEffect(() => place && subscribeMarks(place.name, () => refresh((count) => count + 1)), [place === null || place === void 0 ? void 0 : place.name]);
|
|
1939
|
+
if (!place) return {};
|
|
1940
|
+
const key = reviewKey(place.file, place.target, script);
|
|
1941
|
+
const print = scriptPrint(script);
|
|
1942
|
+
return {
|
|
1943
|
+
reviewed: readMarks(place.name, place.remember)[key] === print,
|
|
1944
|
+
setReviewed(value) {
|
|
1945
|
+
const marks = _objectSpread2({}, readMarks(place.name, place.remember));
|
|
1946
|
+
if (value) marks[key] = print;
|
|
1947
|
+
else delete marks[key];
|
|
1948
|
+
writeMarks(place.name, marks, place.remember);
|
|
1949
|
+
}
|
|
1950
|
+
};
|
|
1951
|
+
}
|
|
1952
|
+
/** One script of a comparison, open, for a tab of its own. */
|
|
1953
|
+
function ScriptReviewTab({ comparison, script, renderBlock, locale = "en", loadAsset, locateBlock, mark }) {
|
|
1954
|
+
const labels = locale.startsWith("ja") ? ja : en;
|
|
1955
|
+
const location = useBlockLocation(comparison, locateBlock);
|
|
1956
|
+
const { reviewed, setReviewed } = useReviewMark(mark, script);
|
|
1957
|
+
return /* @__PURE__ */ React.createElement("section", { className: "twgit-block-diff twgit-review twgit-review-tab" }, /* @__PURE__ */ React.createElement(ScriptComparison, {
|
|
1958
|
+
script,
|
|
1959
|
+
labels,
|
|
1960
|
+
renderBlock,
|
|
1961
|
+
loadAsset,
|
|
1962
|
+
location,
|
|
1963
|
+
expanded: true,
|
|
1964
|
+
reviewed,
|
|
1965
|
+
setReviewed
|
|
1966
|
+
}), /* @__PURE__ */ React.createElement(Legend, { labels }));
|
|
1967
|
+
}
|
|
1968
|
+
/**
|
|
1969
|
+
* What changed in a stage or sprite outside its code, or in the project as a whole when no target is given,
|
|
1970
|
+
* for a tab of its own.
|
|
1971
|
+
*/
|
|
1972
|
+
function TargetReviewTab({ comparison, target, locale = "en", loadAsset }) {
|
|
1973
|
+
const labels = locale.startsWith("ja") ? ja : en;
|
|
1974
|
+
if (!target) return /* @__PURE__ */ React.createElement("section", { className: "twgit-block-diff twgit-review twgit-review-tab" }, comparison.properties.length > 0 ? /* @__PURE__ */ React.createElement("p", null, labels.properties, " · ", propertyNames(comparison.properties, labels)) : /* @__PURE__ */ React.createElement("p", null, labels.noChanges));
|
|
1975
|
+
return /* @__PURE__ */ React.createElement("section", { className: "twgit-block-diff twgit-review twgit-review-tab" }, /* @__PURE__ */ React.createElement("h5", null, /* @__PURE__ */ React.createElement(TargetThumbnails, {
|
|
1976
|
+
target,
|
|
1977
|
+
labels,
|
|
1978
|
+
loadAsset
|
|
1979
|
+
}), target.isStage ? labels.stage : target.name), target.status !== "updated" && /* @__PURE__ */ React.createElement("p", { className: "twgit-review-target-status" }, (target.status === "added" ? labels.targetAdded : labels.targetRemoved)(target.name, target.isStage)), target.status === "updated" && target.properties.length > 0 && /* @__PURE__ */ React.createElement("p", null, labels.properties, " · ", propertyNames(target.properties, labels)), target.scripts.length > 0 && /* @__PURE__ */ React.createElement("p", null, labels.scriptCount(target.scripts.length)));
|
|
1980
|
+
}
|
|
1874
1981
|
// src/github-pull-requests.ts
|
|
1875
1982
|
init_objectSpread2();
|
|
1876
1983
|
var PullRequestError = class extends Error {
|
|
@@ -2116,6 +2223,119 @@ function createGitHubPullRequests(repository, send = fetch) {
|
|
|
2116
2223
|
}
|
|
2117
2224
|
};
|
|
2118
2225
|
}
|
|
2226
|
+
// src/project-source-tabs.tsx
|
|
2227
|
+
var providerId = "turbowarp-plus-git";
|
|
2228
|
+
var statusColor = {
|
|
2229
|
+
added: "green",
|
|
2230
|
+
removed: "red",
|
|
2231
|
+
updated: "blue"
|
|
2232
|
+
};
|
|
2233
|
+
/** Renders its content once the tab is first shown, so a comparison with many scripts draws only what is looked at. */
|
|
2234
|
+
function WhenShown({ children }) {
|
|
2235
|
+
const element = useRef(null);
|
|
2236
|
+
const [shown, setShown] = useState(false);
|
|
2237
|
+
useEffect(() => {
|
|
2238
|
+
var _element$current;
|
|
2239
|
+
const view = (_element$current = element.current) === null || _element$current === void 0 ? void 0 : _element$current.ownerDocument.defaultView;
|
|
2240
|
+
if (shown || !element.current) return;
|
|
2241
|
+
if (!(view === null || view === void 0 ? void 0 : view.IntersectionObserver)) {
|
|
2242
|
+
setShown(true);
|
|
2243
|
+
return;
|
|
2244
|
+
}
|
|
2245
|
+
const observer = new view.IntersectionObserver((entries) => {
|
|
2246
|
+
if (entries.some((entry) => entry.isIntersecting)) setShown(true);
|
|
2247
|
+
});
|
|
2248
|
+
observer.observe(element.current);
|
|
2249
|
+
return () => observer.disconnect();
|
|
2250
|
+
}, [shown]);
|
|
2251
|
+
return /* @__PURE__ */ React.createElement("div", {
|
|
2252
|
+
ref: element,
|
|
2253
|
+
className: "twgit-review-tab-body"
|
|
2254
|
+
}, shown && children);
|
|
2255
|
+
}
|
|
2256
|
+
/**
|
|
2257
|
+
* Opens a comparison of project.source.json files as tabs of the host's workspace: a tab group for each changed
|
|
2258
|
+
* stage or sprite, holding a tab for each changed script and one for its changes outside the code.
|
|
2259
|
+
* Returns how many tabs were asked for, or `0` when the host has no workspace to take them.
|
|
2260
|
+
*/
|
|
2261
|
+
function openProjectSourceTabs(openPanel, { key, files, renderBlock, locale = "en", rememberAs }) {
|
|
2262
|
+
if (!openPanel) return 0;
|
|
2263
|
+
const words = reviewTabWords(locale);
|
|
2264
|
+
const area = `${providerId}:diff:${key}`;
|
|
2265
|
+
const requests = [];
|
|
2266
|
+
const tab = (documentId, title, content, tabGroup) => ({
|
|
2267
|
+
reference: {
|
|
2268
|
+
providerId,
|
|
2269
|
+
documentId: `diff:${key}:${documentId}`
|
|
2270
|
+
},
|
|
2271
|
+
filename: title,
|
|
2272
|
+
title,
|
|
2273
|
+
transient: true,
|
|
2274
|
+
area,
|
|
2275
|
+
tabGroup,
|
|
2276
|
+
inactive: requests.length > 0,
|
|
2277
|
+
mount(element) {
|
|
2278
|
+
element.classList.add("twgit-panel-tab", "twgit-review-tab-slot");
|
|
2279
|
+
render(/* @__PURE__ */ React.createElement(WhenShown, null, content()), element);
|
|
2280
|
+
return {
|
|
2281
|
+
requestClose: () => {},
|
|
2282
|
+
dispose: () => {
|
|
2283
|
+
unmountComponentAtNode(element);
|
|
2284
|
+
}
|
|
2285
|
+
};
|
|
2286
|
+
}
|
|
2287
|
+
});
|
|
2288
|
+
for (const file of files) {
|
|
2289
|
+
const comparison = compareProjectForReview(file.before, file.after);
|
|
2290
|
+
const prefix = files.length > 1 ? file.path.split("/").slice(0, -1).join("/") : "";
|
|
2291
|
+
const labelOf = (target) => prefix ? `${prefix}: ${words.target(target)}` : words.target(target);
|
|
2292
|
+
if (comparison.properties.length || !comparison.targets.length) {
|
|
2293
|
+
const title = prefix ? `${prefix}: ${words.project}` : words.project;
|
|
2294
|
+
requests.push(tab(`${file.path}:project`, title, () => /* @__PURE__ */ React.createElement(TargetReviewTab, {
|
|
2295
|
+
comparison,
|
|
2296
|
+
locale
|
|
2297
|
+
})));
|
|
2298
|
+
}
|
|
2299
|
+
for (const target of comparison.targets) {
|
|
2300
|
+
const targetKey = JSON.stringify([
|
|
2301
|
+
file.path,
|
|
2302
|
+
target.isStage,
|
|
2303
|
+
target.name
|
|
2304
|
+
]);
|
|
2305
|
+
const tabGroup = {
|
|
2306
|
+
id: `${area}:${targetKey}`,
|
|
2307
|
+
label: labelOf(target),
|
|
2308
|
+
color: statusColor[target.status]
|
|
2309
|
+
};
|
|
2310
|
+
if (target.status !== "updated" || target.properties.length || !target.scripts.length) requests.push(tab(`${targetKey}:details`, words.targetDetails, () => /* @__PURE__ */ React.createElement(TargetReviewTab, {
|
|
2311
|
+
comparison,
|
|
2312
|
+
target,
|
|
2313
|
+
locale,
|
|
2314
|
+
loadAsset: file.loadAsset
|
|
2315
|
+
}), tabGroup));
|
|
2316
|
+
for (const script of target.scripts) requests.push(tab(`${targetKey}:${script.id}`, words.script(script), () => /* @__PURE__ */ React.createElement(ScriptReviewTab, {
|
|
2317
|
+
comparison,
|
|
2318
|
+
script,
|
|
2319
|
+
renderBlock,
|
|
2320
|
+
locale,
|
|
2321
|
+
loadAsset: file.loadAsset,
|
|
2322
|
+
locateBlock: file.locateBlock,
|
|
2323
|
+
mark: {
|
|
2324
|
+
name: rememberAs !== null && rememberAs !== void 0 ? rememberAs : area,
|
|
2325
|
+
remember: !!rememberAs,
|
|
2326
|
+
file: file.path,
|
|
2327
|
+
target
|
|
2328
|
+
}
|
|
2329
|
+
}), tabGroup));
|
|
2330
|
+
}
|
|
2331
|
+
}
|
|
2332
|
+
let opened = 0;
|
|
2333
|
+
for (const request of requests) {
|
|
2334
|
+
if (!openPanel(request)) break;
|
|
2335
|
+
opened++;
|
|
2336
|
+
}
|
|
2337
|
+
return opened;
|
|
2338
|
+
}
|
|
2119
2339
|
// src/block-diff-location.ts
|
|
2120
2340
|
function markBlockLocation(block, parts) {
|
|
2121
2341
|
const root = block.getSvgRoot();
|
|
@@ -2473,7 +2693,7 @@ function createScratchBlocksDiffRenderer(options) {
|
|
|
2473
2693
|
init_objectSpread2();
|
|
2474
2694
|
var focusable = "button:not(:disabled), input:not(:disabled), select:not(:disabled), a[href], summary, [tabindex=\"0\"]";
|
|
2475
2695
|
/** A modal that lays project comparisons side by side in sections and asks the user to choose an action. */
|
|
2476
|
-
function ProjectComparisonDialog({ title, description, notes = [], sections, actions, closeLabel
|
|
2696
|
+
function ProjectComparisonDialog({ title, description, notes = [], sections, actions, closeLabel, renderBlock, locale = "en", onChoose }) {
|
|
2477
2697
|
const dialog = useRef(null);
|
|
2478
2698
|
const first = useRef(null);
|
|
2479
2699
|
useEffect(() => {
|
|
@@ -2510,10 +2730,10 @@ function ProjectComparisonDialog({ title, description, notes = [], sections, act
|
|
|
2510
2730
|
"aria-modal": "true",
|
|
2511
2731
|
"aria-label": title,
|
|
2512
2732
|
onKeyDown: keyDown
|
|
2513
|
-
}, /* @__PURE__ */ React.createElement("header", null, /* @__PURE__ */ React.createElement("h2", null, title), /* @__PURE__ */ React.createElement(
|
|
2514
|
-
|
|
2733
|
+
}, /* @__PURE__ */ React.createElement("header", null, /* @__PURE__ */ React.createElement("h2", null, title), /* @__PURE__ */ React.createElement(CloseButton, {
|
|
2734
|
+
label: closeLabel !== null && closeLabel !== void 0 ? closeLabel : locale.startsWith("ja") ? "閉じる" : "Close",
|
|
2515
2735
|
onClick: () => onChoose(null)
|
|
2516
|
-
}
|
|
2736
|
+
})), /* @__PURE__ */ React.createElement("div", { className: "twgit-comparison-body" }, description && /* @__PURE__ */ React.createElement("p", null, description), notes.map((note) => /* @__PURE__ */ React.createElement("p", {
|
|
2517
2737
|
key: note,
|
|
2518
2738
|
role: "note"
|
|
2519
2739
|
}, note)), sections.map((section) => /* @__PURE__ */ React.createElement("section", {
|
|
@@ -2546,4 +2766,4 @@ function openProjectComparison(document, options) {
|
|
|
2546
2766
|
render(/* @__PURE__ */ React.createElement(ProjectComparisonDialog, _objectSpread2(_objectSpread2({}, options), {}, { onChoose: choose })), root);
|
|
2547
2767
|
});
|
|
2548
2768
|
}
|
|
2549
|
-
export {
|
|
2769
|
+
export { parseProjectSource as C, createProjectSourceDiff as S, CloseButton as T, usePreviewSync as _, openProjectSourceTabs as a, useCostumeImage as b, gitHubRepositoryFromOrigin as c, assetFileName as d, organizeProjectChanges as f, createPreviewSync as g, BlockPreview as h, createScratchBlocksDiffLocator as i, ProjectSourceComparison as l, compareProjectForReview as m, openProjectComparison as n, PullRequestError as o, projectPropertyLabel as p, createScratchBlocksDiffRenderer as r, createGitHubPullRequests as s, ProjectComparisonDialog as t, ProjectSourceReview as u, currentCostume as v, readProjectSourceDiff as w, compareProjectBlocks as x, useAssetImage as y };
|
|
@@ -18,6 +18,7 @@ export interface ProjectComparisonOptions {
|
|
|
18
18
|
sections: readonly ProjectComparisonSection[];
|
|
19
19
|
/** The first action is the one the dialog focuses. Closing the dialog or pressing Escape chooses none. */
|
|
20
20
|
actions: readonly ProjectComparisonAction[];
|
|
21
|
+
/** The tooltip and accessible name of the X button that closes the dialog. By default, "Close" in the locale. */
|
|
21
22
|
closeLabel?: string;
|
|
22
23
|
renderBlock: ProjectBlockRenderer;
|
|
23
24
|
locale?: string;
|
|
@@ -5,6 +5,8 @@ import './project-source-diff.css';
|
|
|
5
5
|
export { createGitHubPullRequests, gitHubRepositoryFromOrigin } from './github-pull-requests.js';
|
|
6
6
|
export { ProjectSourceComparison, ProjectSourceReview } from './project-source-review.js';
|
|
7
7
|
export { ProjectComparisonDialog, openProjectComparison } from './project-comparison.js';
|
|
8
|
+
export { openProjectSourceTabs } from './project-source-tabs.js';
|
|
9
|
+
export type { ProjectSourceTabsFile, ProjectSourceTabsOptions } from './project-source-tabs.js';
|
|
8
10
|
export type { ProjectComparisonAction, ProjectComparisonDialogProps, ProjectComparisonOptions, ProjectComparisonSection } from './project-comparison.js';
|
|
9
11
|
export type { ProjectSourceComparisonProps, ProjectSourceReviewFile, ProjectSourceReviewProps } from './project-source-review.js';
|
|
10
12
|
export { createScratchBlocksDiffLocator } from './block-diff-location.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { S as createProjectSourceDiff, _ as usePreviewSync, a as openProjectSourceTabs, c as gitHubRepositoryFromOrigin, d as assetFileName, f as organizeProjectChanges, g as createPreviewSync, h as BlockPreview, i as createScratchBlocksDiffLocator, l as ProjectSourceComparison, m as compareProjectForReview, n as openProjectComparison, p as projectPropertyLabel, r as createScratchBlocksDiffRenderer, s as createGitHubPullRequests, t as ProjectComparisonDialog, u as ProjectSourceReview, v as currentCostume, w as readProjectSourceDiff, x as compareProjectBlocks } from "./project-comparison-1rggIJse.js";
|
|
2
2
|
import { n as init_objectSpread2, t as _objectSpread2 } from "./objectSpread2-Dkd68nJH.js";
|
|
3
3
|
import React, { useEffect, useMemo, useRef, useState } from "react";
|
|
4
4
|
// src/project-source-diff.tsx
|
|
@@ -169,4 +169,4 @@ function ProjectSourceBlockDiff({ patch, beforeSource, renderBlock, locateBlock,
|
|
|
169
169
|
})
|
|
170
170
|
}, labels.more));
|
|
171
171
|
}
|
|
172
|
-
export { ProjectComparisonDialog, ProjectSourceBlockDiff, ProjectSourceComparison, ProjectSourceReview, assetFileName, compareProjectForReview, createGitHubPullRequests, createPreviewSync, createProjectSourceDiff, createScratchBlocksDiffLocator, createScratchBlocksDiffRenderer, currentCostume, gitHubRepositoryFromOrigin, openProjectComparison, organizeProjectChanges, projectPropertyLabel };
|
|
172
|
+
export { ProjectComparisonDialog, ProjectSourceBlockDiff, ProjectSourceComparison, ProjectSourceReview, assetFileName, compareProjectForReview, createGitHubPullRequests, createPreviewSync, createProjectSourceDiff, createScratchBlocksDiffLocator, createScratchBlocksDiffRenderer, currentCostume, gitHubRepositoryFromOrigin, openProjectComparison, openProjectSourceTabs, organizeProjectChanges, projectPropertyLabel };
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
+
import { compareProjectForReview } from './project-source-review-model.js';
|
|
3
|
+
import type { ScriptReview, TargetReview } from './project-source-review-model.js';
|
|
2
4
|
import type { ProjectBlockRenderer } from './scratch-block-diff-renderer.js';
|
|
3
5
|
import type { ProjectBlockLocator } from './block-diff-location.js';
|
|
4
6
|
import type { ProjectAssetLoader } from './project-assets.js';
|
|
7
|
+
type Comparison = ReturnType<typeof compareProjectForReview>;
|
|
5
8
|
export type ProjectSourceReviewFile = {
|
|
6
9
|
path: string;
|
|
7
10
|
summary?: string;
|
|
@@ -51,3 +54,43 @@ export interface ProjectSourceComparisonProps {
|
|
|
51
54
|
/** Compares two versions of a project.source.json by stage, sprite and code, as the pull request review does. */
|
|
52
55
|
export declare function ProjectSourceComparison({ before, after, renderBlock, locale, fallback, loadAsset, locateBlock, target }: ProjectSourceComparisonProps): React.JSX.Element;
|
|
53
56
|
export declare function ProjectSourceReview({ title, description, verification, files, renderBlock, locale, rememberAs }: ProjectSourceReviewProps): React.JSX.Element;
|
|
57
|
+
/** The words of one tab of a project comparison opened as tabs. */
|
|
58
|
+
export declare function reviewTabWords(locale: string): {
|
|
59
|
+
script: (script: ScriptReview) => string;
|
|
60
|
+
target: (target: TargetReview) => string;
|
|
61
|
+
targetDetails: string;
|
|
62
|
+
project: string;
|
|
63
|
+
noChanges: string;
|
|
64
|
+
};
|
|
65
|
+
/**
|
|
66
|
+
* Where a tab keeps its reviewed mark: under `name` with the review of the same name, in the browser when
|
|
67
|
+
* `remember` is set, or else while the page is open.
|
|
68
|
+
*/
|
|
69
|
+
export interface ReviewMarkPlace {
|
|
70
|
+
name: string;
|
|
71
|
+
remember: boolean;
|
|
72
|
+
file: string;
|
|
73
|
+
target: TargetReview;
|
|
74
|
+
}
|
|
75
|
+
/** One script of a comparison, open, for a tab of its own. */
|
|
76
|
+
export declare function ScriptReviewTab({ comparison, script, renderBlock, locale, loadAsset, locateBlock, mark }: {
|
|
77
|
+
comparison: Comparison;
|
|
78
|
+
script: ScriptReview;
|
|
79
|
+
renderBlock: ProjectBlockRenderer;
|
|
80
|
+
locale?: string;
|
|
81
|
+
loadAsset?: ProjectAssetLoader;
|
|
82
|
+
locateBlock?: ProjectBlockLocator;
|
|
83
|
+
/** Offers the reviewed mark, shared with the review panel and other tabs that use the same place. */
|
|
84
|
+
mark?: ReviewMarkPlace;
|
|
85
|
+
}): React.JSX.Element;
|
|
86
|
+
/**
|
|
87
|
+
* What changed in a stage or sprite outside its code, or in the project as a whole when no target is given,
|
|
88
|
+
* for a tab of its own.
|
|
89
|
+
*/
|
|
90
|
+
export declare function TargetReviewTab({ comparison, target, locale, loadAsset }: {
|
|
91
|
+
comparison: Comparison;
|
|
92
|
+
target?: TargetReview;
|
|
93
|
+
locale?: string;
|
|
94
|
+
loadAsset?: ProjectAssetLoader;
|
|
95
|
+
}): React.JSX.Element;
|
|
96
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { ProjectSource } from './project-source-patch.js';
|
|
2
|
+
import type { ProjectBlockRenderer } from './scratch-block-diff-renderer.js';
|
|
3
|
+
import type { ProjectAssetLoader } from './project-assets.js';
|
|
4
|
+
import type { ProjectBlockLocator } from './block-diff-location.js';
|
|
5
|
+
import type { GitPanelRequest } from './index.js';
|
|
6
|
+
/** One project.source.json of a comparison, read into both versions. */
|
|
7
|
+
export interface ProjectSourceTabsFile {
|
|
8
|
+
path: string;
|
|
9
|
+
before: ProjectSource;
|
|
10
|
+
after: ProjectSource;
|
|
11
|
+
loadAsset?: ProjectAssetLoader;
|
|
12
|
+
/** Offers "Highlight in Editor" on the after version, which the caller has matched with the open project. */
|
|
13
|
+
locateBlock?: ProjectBlockLocator;
|
|
14
|
+
}
|
|
15
|
+
export interface ProjectSourceTabsOptions {
|
|
16
|
+
/**
|
|
17
|
+
* Names this comparison, such as `owner/repo#42@<head>` or `<commit>:project.source.json`. Its tabs share one
|
|
18
|
+
* split, and opening the same comparison again brings its tabs forward instead of adding them twice.
|
|
19
|
+
*/
|
|
20
|
+
key: string;
|
|
21
|
+
files: readonly ProjectSourceTabsFile[];
|
|
22
|
+
renderBlock: ProjectBlockRenderer;
|
|
23
|
+
locale?: string;
|
|
24
|
+
/**
|
|
25
|
+
* Shares the reviewed marks of the script tabs with the review of this name, such as `owner/repo#42`, and keeps
|
|
26
|
+
* them in the browser. Without it, the marks are kept for this comparison while the page is open.
|
|
27
|
+
*/
|
|
28
|
+
rememberAs?: string;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Opens a comparison of project.source.json files as tabs of the host's workspace: a tab group for each changed
|
|
32
|
+
* stage or sprite, holding a tab for each changed script and one for its changes outside the code.
|
|
33
|
+
* Returns how many tabs were asked for, or `0` when the host has no workspace to take them.
|
|
34
|
+
*/
|
|
35
|
+
export declare function openProjectSourceTabs(openPanel: ((request: GitPanelRequest) => boolean) | undefined, { key, files, renderBlock, locale, rememberAs }: ProjectSourceTabsOptions): number;
|
|
@@ -2,10 +2,15 @@ import React from 'react';
|
|
|
2
2
|
import type { ProjectBlockRenderer } from './scratch-block-diff-renderer.js';
|
|
3
3
|
import type { Repository } from './repository.js';
|
|
4
4
|
import type { ProjectBlockLocator } from './block-diff-location.js';
|
|
5
|
-
|
|
5
|
+
import type { ProjectSourceTabsFile } from './project-source-tabs.js';
|
|
6
|
+
type OpenTabs = (key: string, files: readonly ProjectSourceTabsFile[], rememberAs?: string) => number;
|
|
7
|
+
export declare function PullRequestReviewPanel({ repository, locale, renderBlock, locateFor, openTabs }: {
|
|
6
8
|
repository: Repository;
|
|
7
9
|
locale: string;
|
|
8
10
|
renderBlock: ProjectBlockRenderer;
|
|
11
|
+
/** Opens a pull request's project changes as tabs of the host's layout. */
|
|
12
|
+
openTabs?: OpenTabs;
|
|
9
13
|
/** Returns a locator for a project file whose PR head matches the open project, or `undefined`. */
|
|
10
14
|
locateFor?(path: string, headSha: string): ProjectBlockLocator | undefined;
|
|
11
15
|
}): React.JSX.Element;
|
|
16
|
+
export {};
|