forked from Kieran/zap.stream
Compare commits
10 Commits
type-error
...
main
Author | SHA1 | Date | |
---|---|---|---|
7cba67e4c1 | |||
c191a7684a | |||
0e590feab4 | |||
16c54185bb | |||
d071736d4c | |||
f7517d7e1a | |||
|
9741eb6a83 | ||
|
cb94afdc16 | ||
|
5a24671839 | ||
6b328a1fde |
@ -22,4 +22,4 @@ steps:
|
||||
volumes:
|
||||
- name: cache
|
||||
claim:
|
||||
name: docker-cache
|
||||
name: docker-cache
|
||||
|
@ -1,20 +1,19 @@
|
||||
module.exports = {
|
||||
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["@typescript-eslint"],
|
||||
root: true,
|
||||
ignorePatterns: ["build/", "*.test.ts", "*.js"],
|
||||
env: {
|
||||
browser: true,
|
||||
worker: true,
|
||||
commonjs: true,
|
||||
node: false,
|
||||
},
|
||||
"rules": {
|
||||
"@typescript-eslint/no-non-null-assertion": "error",
|
||||
"require-await": "error",
|
||||
"eqeqeq": "error",
|
||||
"object-shorthand": "warn",
|
||||
}
|
||||
};
|
||||
|
||||
extends: ["eslint:recommended", "plugin:@typescript-eslint/recommended"],
|
||||
parser: "@typescript-eslint/parser",
|
||||
plugins: ["@typescript-eslint"],
|
||||
root: true,
|
||||
ignorePatterns: ["build/", "*.test.ts", "*.js"],
|
||||
env: {
|
||||
browser: true,
|
||||
worker: true,
|
||||
commonjs: true,
|
||||
node: false,
|
||||
},
|
||||
rules: {
|
||||
"@typescript-eslint/no-non-null-assertion": "error",
|
||||
"require-await": "error",
|
||||
eqeqeq: "error",
|
||||
"object-shorthand": "warn",
|
||||
},
|
||||
};
|
||||
|
6
.yarn/sdks/eslint/bin/eslint.js
vendored
6
.yarn/sdks/eslint/bin/eslint.js
vendored
@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
|
6
.yarn/sdks/eslint/lib/api.js
vendored
6
.yarn/sdks/eslint/lib/api.js
vendored
@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
|
6
.yarn/sdks/prettier/index.js
vendored
6
.yarn/sdks/prettier/index.js
vendored
@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../.pnp.cjs";
|
||||
|
||||
|
6
.yarn/sdks/typescript/lib/tsc.js
vendored
6
.yarn/sdks/typescript/lib/tsc.js
vendored
@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
|
185
.yarn/sdks/typescript/lib/tsserver.js
vendored
185
.yarn/sdks/typescript/lib/tsserver.js
vendored
@ -1,29 +1,31 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const moduleWrapper = tsserver => {
|
||||
const moduleWrapper = (tsserver) => {
|
||||
if (!process.versions.pnp) {
|
||||
return tsserver;
|
||||
}
|
||||
|
||||
const {isAbsolute} = require(`path`);
|
||||
const { isAbsolute } = require(`path`);
|
||||
const pnpApi = require(`pnpapi`);
|
||||
|
||||
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
|
||||
const isPortal = str => str.startsWith("portal:/");
|
||||
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
|
||||
const isVirtual = (str) => str.match(/\/(\$\$virtual|__virtual__)\//);
|
||||
const isPortal = (str) => str.startsWith("portal:/");
|
||||
const normalize = (str) => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
|
||||
|
||||
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
|
||||
return `${locator.name}@${locator.reference}`;
|
||||
}));
|
||||
const dependencyTreeRoots = new Set(
|
||||
pnpApi.getDependencyTreeRoots().map((locator) => {
|
||||
return `${locator.name}@${locator.reference}`;
|
||||
})
|
||||
);
|
||||
|
||||
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
|
||||
// doesn't understand. This layer makes sure to remove the protocol
|
||||
@ -31,7 +33,11 @@ const moduleWrapper = tsserver => {
|
||||
|
||||
function toEditorPath(str) {
|
||||
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
|
||||
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
|
||||
if (
|
||||
isAbsolute(str) &&
|
||||
!str.match(/^\^?(zip:|\/zip\/)/) &&
|
||||
(str.match(/\.zip\//) || isVirtual(str))
|
||||
) {
|
||||
// We also take the opportunity to turn virtual paths into physical ones;
|
||||
// this makes it much easier to work with workspaces that list peer
|
||||
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
|
||||
@ -45,7 +51,11 @@ const moduleWrapper = tsserver => {
|
||||
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
|
||||
if (resolved) {
|
||||
const locator = pnpApi.findPackageLocator(resolved);
|
||||
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
|
||||
if (
|
||||
locator &&
|
||||
(dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) ||
|
||||
isPortal(locator.reference))
|
||||
) {
|
||||
str = resolved;
|
||||
}
|
||||
}
|
||||
@ -73,41 +83,55 @@ const moduleWrapper = tsserver => {
|
||||
// Before | ^/zip/c:/foo/bar.zip/package.json
|
||||
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||
//
|
||||
case `vscode <1.61`: {
|
||||
str = `^zip:${str}`;
|
||||
} break;
|
||||
case `vscode <1.61`:
|
||||
{
|
||||
str = `^zip:${str}`;
|
||||
}
|
||||
break;
|
||||
|
||||
case `vscode <1.66`: {
|
||||
str = `^/zip/${str}`;
|
||||
} break;
|
||||
case `vscode <1.66`:
|
||||
{
|
||||
str = `^/zip/${str}`;
|
||||
}
|
||||
break;
|
||||
|
||||
case `vscode <1.68`: {
|
||||
str = `^/zip${str}`;
|
||||
} break;
|
||||
case `vscode <1.68`:
|
||||
{
|
||||
str = `^/zip${str}`;
|
||||
}
|
||||
break;
|
||||
|
||||
case `vscode`: {
|
||||
str = `^/zip/${str}`;
|
||||
} break;
|
||||
case `vscode`:
|
||||
{
|
||||
str = `^/zip/${str}`;
|
||||
}
|
||||
break;
|
||||
|
||||
// To make "go to definition" work,
|
||||
// We have to resolve the actual file system path from virtual path
|
||||
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
|
||||
case `coc-nvim`: {
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = resolve(`zipfile:${str}`);
|
||||
} break;
|
||||
case `coc-nvim`:
|
||||
{
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = resolve(`zipfile:${str}`);
|
||||
}
|
||||
break;
|
||||
|
||||
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
|
||||
// We have to resolve the actual file system path from virtual path,
|
||||
// everything else is up to neovim
|
||||
case `neovim`: {
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = `zipfile://${str}`;
|
||||
} break;
|
||||
case `neovim`:
|
||||
{
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = `zipfile://${str}`;
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
str = `zip:${str}`;
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
str = `zip:${str}`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
|
||||
@ -119,26 +143,35 @@ const moduleWrapper = tsserver => {
|
||||
|
||||
function fromEditorPath(str) {
|
||||
switch (hostInfo) {
|
||||
case `coc-nvim`: {
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
|
||||
// So in order to convert it back, we use .* to match all the thing
|
||||
// before `zipfile:`
|
||||
return process.platform === `win32`
|
||||
? str.replace(/^.*zipfile:\//, ``)
|
||||
: str.replace(/^.*zipfile:/, ``);
|
||||
} break;
|
||||
case `coc-nvim`:
|
||||
{
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
|
||||
// So in order to convert it back, we use .* to match all the thing
|
||||
// before `zipfile:`
|
||||
return process.platform === `win32`
|
||||
? str.replace(/^.*zipfile:\//, ``)
|
||||
: str.replace(/^.*zipfile:/, ``);
|
||||
}
|
||||
break;
|
||||
|
||||
case `neovim`: {
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
|
||||
return str.replace(/^zipfile:\/\//, ``);
|
||||
} break;
|
||||
case `neovim`:
|
||||
{
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
|
||||
return str.replace(/^zipfile:\/\//, ``);
|
||||
}
|
||||
break;
|
||||
|
||||
case `vscode`:
|
||||
default: {
|
||||
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
return str.replace(
|
||||
/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/,
|
||||
process.platform === `win32` ? `` : `/`
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,8 +183,9 @@ const moduleWrapper = tsserver => {
|
||||
// TypeScript already does local loads and if this code is running the user trusts the workspace
|
||||
// https://github.com/microsoft/vscode/issues/45856
|
||||
const ConfiguredProject = tsserver.server.ConfiguredProject;
|
||||
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
|
||||
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
|
||||
const { enablePluginsWithOptions: originalEnablePluginsWithOptions } =
|
||||
ConfiguredProject.prototype;
|
||||
ConfiguredProject.prototype.enablePluginsWithOptions = function () {
|
||||
this.projectService.allowLocalPluginLoads = true;
|
||||
return originalEnablePluginsWithOptions.apply(this, arguments);
|
||||
};
|
||||
@ -161,12 +195,13 @@ const moduleWrapper = tsserver => {
|
||||
// like an absolute path of ours and normalize it.
|
||||
|
||||
const Session = tsserver.server.Session;
|
||||
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
|
||||
const { onMessage: originalOnMessage, send: originalSend } =
|
||||
Session.prototype;
|
||||
let hostInfo = `unknown`;
|
||||
|
||||
Object.assign(Session.prototype, {
|
||||
onMessage(/** @type {string | object} */ message) {
|
||||
const isStringMessage = typeof message === 'string';
|
||||
const isStringMessage = typeof message === "string";
|
||||
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
|
||||
|
||||
if (
|
||||
@ -177,10 +212,12 @@ const moduleWrapper = tsserver => {
|
||||
) {
|
||||
hostInfo = parsedMessage.arguments.hostInfo;
|
||||
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
|
||||
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
|
||||
// The RegExp from https://semver.org/ but without the caret at the start
|
||||
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
|
||||
) ?? []).map(Number)
|
||||
const [, major, minor] = (
|
||||
process.env.VSCODE_IPC_HOOK.match(
|
||||
// The RegExp from https://semver.org/ but without the caret at the start
|
||||
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
|
||||
) ?? []
|
||||
).map(Number);
|
||||
|
||||
if (major === 1) {
|
||||
if (minor < 61) {
|
||||
@ -194,21 +231,31 @@ const moduleWrapper = tsserver => {
|
||||
}
|
||||
}
|
||||
|
||||
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
|
||||
return typeof value === 'string' ? fromEditorPath(value) : value;
|
||||
});
|
||||
const processedMessageJSON = JSON.stringify(
|
||||
parsedMessage,
|
||||
(key, value) => {
|
||||
return typeof value === "string" ? fromEditorPath(value) : value;
|
||||
}
|
||||
);
|
||||
|
||||
return originalOnMessage.call(
|
||||
this,
|
||||
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
|
||||
isStringMessage
|
||||
? processedMessageJSON
|
||||
: JSON.parse(processedMessageJSON)
|
||||
);
|
||||
},
|
||||
|
||||
send(/** @type {any} */ msg) {
|
||||
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
|
||||
return typeof value === `string` ? toEditorPath(value) : value;
|
||||
})));
|
||||
}
|
||||
return originalSend.call(
|
||||
this,
|
||||
JSON.parse(
|
||||
JSON.stringify(msg, (key, value) => {
|
||||
return typeof value === `string` ? toEditorPath(value) : value;
|
||||
})
|
||||
)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return tsserver;
|
||||
|
185
.yarn/sdks/typescript/lib/tsserverlibrary.js
vendored
185
.yarn/sdks/typescript/lib/tsserverlibrary.js
vendored
@ -1,29 +1,31 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
const absPnpApiPath = resolve(__dirname, relPnpApiPath);
|
||||
const absRequire = createRequire(absPnpApiPath);
|
||||
|
||||
const moduleWrapper = tsserver => {
|
||||
const moduleWrapper = (tsserver) => {
|
||||
if (!process.versions.pnp) {
|
||||
return tsserver;
|
||||
}
|
||||
|
||||
const {isAbsolute} = require(`path`);
|
||||
const { isAbsolute } = require(`path`);
|
||||
const pnpApi = require(`pnpapi`);
|
||||
|
||||
const isVirtual = str => str.match(/\/(\$\$virtual|__virtual__)\//);
|
||||
const isPortal = str => str.startsWith("portal:/");
|
||||
const normalize = str => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
|
||||
const isVirtual = (str) => str.match(/\/(\$\$virtual|__virtual__)\//);
|
||||
const isPortal = (str) => str.startsWith("portal:/");
|
||||
const normalize = (str) => str.replace(/\\/g, `/`).replace(/^\/?/, `/`);
|
||||
|
||||
const dependencyTreeRoots = new Set(pnpApi.getDependencyTreeRoots().map(locator => {
|
||||
return `${locator.name}@${locator.reference}`;
|
||||
}));
|
||||
const dependencyTreeRoots = new Set(
|
||||
pnpApi.getDependencyTreeRoots().map((locator) => {
|
||||
return `${locator.name}@${locator.reference}`;
|
||||
})
|
||||
);
|
||||
|
||||
// VSCode sends the zip paths to TS using the "zip://" prefix, that TS
|
||||
// doesn't understand. This layer makes sure to remove the protocol
|
||||
@ -31,7 +33,11 @@ const moduleWrapper = tsserver => {
|
||||
|
||||
function toEditorPath(str) {
|
||||
// We add the `zip:` prefix to both `.zip/` paths and virtual paths
|
||||
if (isAbsolute(str) && !str.match(/^\^?(zip:|\/zip\/)/) && (str.match(/\.zip\//) || isVirtual(str))) {
|
||||
if (
|
||||
isAbsolute(str) &&
|
||||
!str.match(/^\^?(zip:|\/zip\/)/) &&
|
||||
(str.match(/\.zip\//) || isVirtual(str))
|
||||
) {
|
||||
// We also take the opportunity to turn virtual paths into physical ones;
|
||||
// this makes it much easier to work with workspaces that list peer
|
||||
// dependencies, since otherwise Ctrl+Click would bring us to the virtual
|
||||
@ -45,7 +51,11 @@ const moduleWrapper = tsserver => {
|
||||
const resolved = isVirtual(str) ? pnpApi.resolveVirtual(str) : str;
|
||||
if (resolved) {
|
||||
const locator = pnpApi.findPackageLocator(resolved);
|
||||
if (locator && (dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) || isPortal(locator.reference))) {
|
||||
if (
|
||||
locator &&
|
||||
(dependencyTreeRoots.has(`${locator.name}@${locator.reference}`) ||
|
||||
isPortal(locator.reference))
|
||||
) {
|
||||
str = resolved;
|
||||
}
|
||||
}
|
||||
@ -73,41 +83,55 @@ const moduleWrapper = tsserver => {
|
||||
// Before | ^/zip/c:/foo/bar.zip/package.json
|
||||
// After | ^/zip//c:/foo/bar.zip/package.json
|
||||
//
|
||||
case `vscode <1.61`: {
|
||||
str = `^zip:${str}`;
|
||||
} break;
|
||||
case `vscode <1.61`:
|
||||
{
|
||||
str = `^zip:${str}`;
|
||||
}
|
||||
break;
|
||||
|
||||
case `vscode <1.66`: {
|
||||
str = `^/zip/${str}`;
|
||||
} break;
|
||||
case `vscode <1.66`:
|
||||
{
|
||||
str = `^/zip/${str}`;
|
||||
}
|
||||
break;
|
||||
|
||||
case `vscode <1.68`: {
|
||||
str = `^/zip${str}`;
|
||||
} break;
|
||||
case `vscode <1.68`:
|
||||
{
|
||||
str = `^/zip${str}`;
|
||||
}
|
||||
break;
|
||||
|
||||
case `vscode`: {
|
||||
str = `^/zip/${str}`;
|
||||
} break;
|
||||
case `vscode`:
|
||||
{
|
||||
str = `^/zip/${str}`;
|
||||
}
|
||||
break;
|
||||
|
||||
// To make "go to definition" work,
|
||||
// We have to resolve the actual file system path from virtual path
|
||||
// and convert scheme to supported by [vim-rzip](https://github.com/lbrayner/vim-rzip)
|
||||
case `coc-nvim`: {
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = resolve(`zipfile:${str}`);
|
||||
} break;
|
||||
case `coc-nvim`:
|
||||
{
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = resolve(`zipfile:${str}`);
|
||||
}
|
||||
break;
|
||||
|
||||
// Support neovim native LSP and [typescript-language-server](https://github.com/theia-ide/typescript-language-server)
|
||||
// We have to resolve the actual file system path from virtual path,
|
||||
// everything else is up to neovim
|
||||
case `neovim`: {
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = `zipfile://${str}`;
|
||||
} break;
|
||||
case `neovim`:
|
||||
{
|
||||
str = normalize(resolved).replace(/\.zip\//, `.zip::`);
|
||||
str = `zipfile://${str}`;
|
||||
}
|
||||
break;
|
||||
|
||||
default: {
|
||||
str = `zip:${str}`;
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
str = `zip:${str}`;
|
||||
}
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
str = str.replace(/^\/?/, process.platform === `win32` ? `` : `/`);
|
||||
@ -119,26 +143,35 @@ const moduleWrapper = tsserver => {
|
||||
|
||||
function fromEditorPath(str) {
|
||||
switch (hostInfo) {
|
||||
case `coc-nvim`: {
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
|
||||
// So in order to convert it back, we use .* to match all the thing
|
||||
// before `zipfile:`
|
||||
return process.platform === `win32`
|
||||
? str.replace(/^.*zipfile:\//, ``)
|
||||
: str.replace(/^.*zipfile:/, ``);
|
||||
} break;
|
||||
case `coc-nvim`:
|
||||
{
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for coc-nvim is in format of /<pwd>/zipfile:/<pwd>/.yarn/...
|
||||
// So in order to convert it back, we use .* to match all the thing
|
||||
// before `zipfile:`
|
||||
return process.platform === `win32`
|
||||
? str.replace(/^.*zipfile:\//, ``)
|
||||
: str.replace(/^.*zipfile:/, ``);
|
||||
}
|
||||
break;
|
||||
|
||||
case `neovim`: {
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
|
||||
return str.replace(/^zipfile:\/\//, ``);
|
||||
} break;
|
||||
case `neovim`:
|
||||
{
|
||||
str = str.replace(/\.zip::/, `.zip/`);
|
||||
// The path for neovim is in format of zipfile:///<pwd>/.yarn/...
|
||||
return str.replace(/^zipfile:\/\//, ``);
|
||||
}
|
||||
break;
|
||||
|
||||
case `vscode`:
|
||||
default: {
|
||||
return str.replace(/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/, process.platform === `win32` ? `` : `/`)
|
||||
} break;
|
||||
default:
|
||||
{
|
||||
return str.replace(
|
||||
/^\^?(zip:|\/zip(\/ts-nul-authority)?)\/+/,
|
||||
process.platform === `win32` ? `` : `/`
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -150,8 +183,9 @@ const moduleWrapper = tsserver => {
|
||||
// TypeScript already does local loads and if this code is running the user trusts the workspace
|
||||
// https://github.com/microsoft/vscode/issues/45856
|
||||
const ConfiguredProject = tsserver.server.ConfiguredProject;
|
||||
const {enablePluginsWithOptions: originalEnablePluginsWithOptions} = ConfiguredProject.prototype;
|
||||
ConfiguredProject.prototype.enablePluginsWithOptions = function() {
|
||||
const { enablePluginsWithOptions: originalEnablePluginsWithOptions } =
|
||||
ConfiguredProject.prototype;
|
||||
ConfiguredProject.prototype.enablePluginsWithOptions = function () {
|
||||
this.projectService.allowLocalPluginLoads = true;
|
||||
return originalEnablePluginsWithOptions.apply(this, arguments);
|
||||
};
|
||||
@ -161,12 +195,13 @@ const moduleWrapper = tsserver => {
|
||||
// like an absolute path of ours and normalize it.
|
||||
|
||||
const Session = tsserver.server.Session;
|
||||
const {onMessage: originalOnMessage, send: originalSend} = Session.prototype;
|
||||
const { onMessage: originalOnMessage, send: originalSend } =
|
||||
Session.prototype;
|
||||
let hostInfo = `unknown`;
|
||||
|
||||
Object.assign(Session.prototype, {
|
||||
onMessage(/** @type {string | object} */ message) {
|
||||
const isStringMessage = typeof message === 'string';
|
||||
const isStringMessage = typeof message === "string";
|
||||
const parsedMessage = isStringMessage ? JSON.parse(message) : message;
|
||||
|
||||
if (
|
||||
@ -177,10 +212,12 @@ const moduleWrapper = tsserver => {
|
||||
) {
|
||||
hostInfo = parsedMessage.arguments.hostInfo;
|
||||
if (hostInfo === `vscode` && process.env.VSCODE_IPC_HOOK) {
|
||||
const [, major, minor] = (process.env.VSCODE_IPC_HOOK.match(
|
||||
// The RegExp from https://semver.org/ but without the caret at the start
|
||||
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
|
||||
) ?? []).map(Number)
|
||||
const [, major, minor] = (
|
||||
process.env.VSCODE_IPC_HOOK.match(
|
||||
// The RegExp from https://semver.org/ but without the caret at the start
|
||||
/(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/
|
||||
) ?? []
|
||||
).map(Number);
|
||||
|
||||
if (major === 1) {
|
||||
if (minor < 61) {
|
||||
@ -194,21 +231,31 @@ const moduleWrapper = tsserver => {
|
||||
}
|
||||
}
|
||||
|
||||
const processedMessageJSON = JSON.stringify(parsedMessage, (key, value) => {
|
||||
return typeof value === 'string' ? fromEditorPath(value) : value;
|
||||
});
|
||||
const processedMessageJSON = JSON.stringify(
|
||||
parsedMessage,
|
||||
(key, value) => {
|
||||
return typeof value === "string" ? fromEditorPath(value) : value;
|
||||
}
|
||||
);
|
||||
|
||||
return originalOnMessage.call(
|
||||
this,
|
||||
isStringMessage ? processedMessageJSON : JSON.parse(processedMessageJSON)
|
||||
isStringMessage
|
||||
? processedMessageJSON
|
||||
: JSON.parse(processedMessageJSON)
|
||||
);
|
||||
},
|
||||
|
||||
send(/** @type {any} */ msg) {
|
||||
return originalSend.call(this, JSON.parse(JSON.stringify(msg, (key, value) => {
|
||||
return typeof value === `string` ? toEditorPath(value) : value;
|
||||
})));
|
||||
}
|
||||
return originalSend.call(
|
||||
this,
|
||||
JSON.parse(
|
||||
JSON.stringify(msg, (key, value) => {
|
||||
return typeof value === `string` ? toEditorPath(value) : value;
|
||||
})
|
||||
)
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
return tsserver;
|
||||
|
6
.yarn/sdks/typescript/lib/typescript.js
vendored
6
.yarn/sdks/typescript/lib/typescript.js
vendored
@ -1,8 +1,8 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
const {existsSync} = require(`fs`);
|
||||
const {createRequire} = require(`module`);
|
||||
const {resolve} = require(`path`);
|
||||
const { existsSync } = require(`fs`);
|
||||
const { createRequire } = require(`module`);
|
||||
const { resolve } = require(`path`);
|
||||
|
||||
const relPnpApiPath = "../../../../.pnp.cjs";
|
||||
|
||||
|
2
_headers
2
_headers
@ -1,2 +1,2 @@
|
||||
/*
|
||||
Content-Security-Policy: default-src 'self'; manifest-src *; child-src 'none'; worker-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; connect-src *; img-src * data: blob:; font-src https://fonts.gstatic.com; media-src * blob:; script-src 'self';
|
||||
Content-Security-Policy: default-src 'self'; manifest-src *; child-src 'none'; worker-src 'self'; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; connect-src *; img-src * data: blob:; font-src 'self'; media-src * blob:; script-src 'self';
|
@ -1,21 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="Nostr live streaming" />
|
||||
<link rel="apple-touch-icon" href="/logo.png" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<title>zap.stream</title>
|
||||
</head>
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<meta name="theme-color" content="#000000" />
|
||||
<meta name="description" content="Nostr live streaming" />
|
||||
<link rel="apple-touch-icon" href="/logo.png" />
|
||||
<link rel="icon" href="/favicon.ico" />
|
||||
<link rel="manifest" href="/manifest.json" />
|
||||
<title>zap.stream</title>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||
<link href="https://fonts.googleapis.com/css2?family=Outfit:wght@400;500;600;700&display=swap" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
<body>
|
||||
<div id="root"></div>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -1,3 +1 @@
|
||||
[
|
||||
{ "id": "nsfw", "text": "NSFW" }
|
||||
]
|
||||
[{ "id": "nsfw", "text": "NSFW" }]
|
||||
|
@ -65,7 +65,7 @@ export function ChatMessage({
|
||||
inView?.isIntersecting ? ev.pubkey : undefined
|
||||
);
|
||||
const shouldShowMuteButton =
|
||||
ev.pubkey !== streamer && ev.pubkey != login?.pubkey;
|
||||
ev.pubkey !== streamer && ev.pubkey !== login?.pubkey;
|
||||
const zapTarget = profile?.lud16 ?? profile?.lud06;
|
||||
const zaps = useMemo(() => {
|
||||
return reactions
|
||||
@ -111,8 +111,8 @@ export function ChatMessage({
|
||||
const pub = login?.publisher();
|
||||
if (emoji.native) {
|
||||
reply = await pub?.react(ev, emoji.native || "+1");
|
||||
} else {
|
||||
const e = getEmojiById(emoji.id!);
|
||||
} else if (emoji.id) {
|
||||
const e = getEmojiById(emoji.id);
|
||||
if (e) {
|
||||
reply = await pub?.generic((eb) => {
|
||||
return eb
|
||||
@ -120,7 +120,7 @@ export function ChatMessage({
|
||||
.content(`:${emoji.id}:`)
|
||||
.tag(["e", ev.id])
|
||||
.tag(["p", ev.pubkey])
|
||||
.tag(["emoji", e.at(1)!, e.at(2)!]);
|
||||
.tag(["emoji", e[1], e[2]]);
|
||||
});
|
||||
}
|
||||
}
|
||||
@ -141,7 +141,7 @@ export function ChatMessage({
|
||||
setShowEmojiPicker(!showEmojiPicker);
|
||||
}
|
||||
|
||||
async function muteUser(e: React.MouseEvent) {
|
||||
function muteUser(e: React.MouseEvent) {
|
||||
e.stopPropagation();
|
||||
mute();
|
||||
}
|
||||
@ -194,7 +194,7 @@ export function ChatMessage({
|
||||
<div className="message-reaction-container">
|
||||
{isCustomEmojiReaction && emoji ? (
|
||||
<span className="message-reaction">
|
||||
<EmojiComponent name={emoji.at(1)!} url={emoji.at(2)!} />
|
||||
<EmojiComponent name={emoji[1]} url={emoji[2]} />
|
||||
</span>
|
||||
) : (
|
||||
<span className="message-reaction">{e}</span>
|
||||
|
@ -12,7 +12,9 @@ export function LoggedInFollowButton({
|
||||
value: string;
|
||||
}) {
|
||||
const login = useLogin();
|
||||
const { tags, content, timestamp } = login!.follows;
|
||||
if (!login) return;
|
||||
|
||||
const { tags, content, timestamp } = login.follows;
|
||||
const follows = tags.filter((t) => t.at(0) === tag);
|
||||
const isFollowing = follows.find((t) => t.at(1) === value);
|
||||
|
||||
|
@ -52,7 +52,7 @@
|
||||
}
|
||||
|
||||
.live-chat > .write-message > div:nth-child(1) {
|
||||
height: 32px;
|
||||
height: 40px;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
@ -325,8 +325,6 @@
|
||||
text-transform: lowercase;
|
||||
color: #fff;
|
||||
font-size: 12px;
|
||||
font-family: Outfit;
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
line-height: 18px;
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ import {
|
||||
parseZap,
|
||||
encodeTLV,
|
||||
} from "@snort/system";
|
||||
import { unixNow } from "@snort/shared";
|
||||
import { unixNow, unwrap } from "@snort/shared";
|
||||
import { useEffect, useMemo } from "react";
|
||||
import uniqBy from "lodash.uniqby";
|
||||
|
||||
@ -96,7 +96,7 @@ export function LiveChat({
|
||||
const login = useLogin();
|
||||
useEffect(() => {
|
||||
const pubkeys = [
|
||||
...new Set(feed.zaps.flatMap((a) => [a.pubkey, findTag(a, "p")!])),
|
||||
...new Set(feed.zaps.flatMap((a) => [a.pubkey, unwrap(findTag(a, "p"))])),
|
||||
];
|
||||
System.ProfileLoader.TrackMetadata(pubkeys);
|
||||
return () => System.ProfileLoader.UntrackMetadata(pubkeys);
|
||||
|
@ -9,6 +9,7 @@ import { StreamEditor, StreamEditorProps } from "./stream-editor";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { eventLink, findTag } from "utils";
|
||||
import { NostrProviderDialog } from "./nostr-provider-dialog";
|
||||
import { unwrap } from "@snort/shared";
|
||||
|
||||
function NewStream({ ev, onFinish }: StreamEditorProps) {
|
||||
const providers = useStreamProvider();
|
||||
@ -19,7 +20,7 @@ function NewStream({ ev, onFinish }: StreamEditorProps) {
|
||||
if (!currentProvider) {
|
||||
setCurrentProvider(
|
||||
ev !== undefined
|
||||
? providers.find((a) => a.name.toLowerCase() === "manual")!
|
||||
? unwrap(providers.find((a) => a.name.toLowerCase() === "manual"))
|
||||
: providers.at(0)
|
||||
);
|
||||
}
|
||||
@ -35,7 +36,11 @@ function NewStream({ ev, onFinish }: StreamEditorProps) {
|
||||
onFinish={(ex) => {
|
||||
currentProvider.updateStreamInfo(ex);
|
||||
if (!ev) {
|
||||
if (findTag(ex, "content-warning") && __XXX_HOST && __XXX === false) {
|
||||
if (
|
||||
findTag(ex, "content-warning") &&
|
||||
__XXX_HOST &&
|
||||
__XXX === false
|
||||
) {
|
||||
location.href = `${__XXX_HOST}/${eventLink(ex)}`;
|
||||
} else {
|
||||
navigate(`/${eventLink(ex)}`, {
|
||||
|
@ -6,7 +6,7 @@
|
||||
|
||||
.send-zap .amounts {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(4, 1fr);
|
||||
grid-template-columns: repeat(6, 1fr);
|
||||
justify-content: space-evenly;
|
||||
gap: 8px;
|
||||
}
|
||||
|
@ -43,10 +43,11 @@ export function SendZaps({
|
||||
targetName,
|
||||
onFinish,
|
||||
}: SendZapsProps) {
|
||||
const UsdRate = 30_000;
|
||||
const UsdRate = 28_000;
|
||||
|
||||
const satsAmounts = [
|
||||
100, 1_000, 5_000, 10_000, 50_000, 100_000, 500_000, 1_000_000,
|
||||
21, 69, 121, 221, 420, 1_000, 2_100, 5_000, 6_666, 10_000, 21_000, 42_000,
|
||||
69_000, 100_000, 210_000, 500_000, 1_000_000,
|
||||
];
|
||||
const usdAmounts = [0.05, 0.5, 2, 5, 10, 50, 100, 200];
|
||||
const [isFiat, setIsFiat] = useState(false);
|
||||
|
@ -1,9 +1,11 @@
|
||||
import { Menu, MenuItem } from "@szhsin/react-menu";
|
||||
import * as Dialog from "@radix-ui/react-dialog";
|
||||
import { unwrap } from "@snort/shared";
|
||||
import { NostrEvent, NostrPrefix, encodeTLV } from "@snort/system";
|
||||
|
||||
import { Icon } from "./icon";
|
||||
import { useState } from "react";
|
||||
import { Textarea } from "./textarea";
|
||||
import { NostrEvent, NostrPrefix, encodeTLV } from "@snort/system";
|
||||
import { findTag } from "utils";
|
||||
import AsyncButton from "./async-button";
|
||||
import { useLogin } from "hooks/login";
|
||||
@ -18,7 +20,7 @@ export function ShareMenu({ ev }: { ev: NostrEvent }) {
|
||||
|
||||
const naddr = encodeTLV(
|
||||
NostrPrefix.Address,
|
||||
findTag(ev, "d")!,
|
||||
unwrap(findTag(ev, "d")),
|
||||
undefined,
|
||||
ev.kind,
|
||||
ev.pubkey
|
||||
|
@ -100,7 +100,7 @@ function Card({ canEdit, ev, cards }: CardProps) {
|
||||
);
|
||||
|
||||
function findTagByIdentifier(d: string) {
|
||||
return tags.find((t) => t.at(1)!.endsWith(`:${d}`));
|
||||
return tags.find((t) => t[1].endsWith(`:${d}`));
|
||||
}
|
||||
|
||||
const [dropStyle, dropRef] = useDrop(
|
||||
@ -293,7 +293,7 @@ function EditCard({ card, cards }: EditCardProps) {
|
||||
async function onCancel() {
|
||||
const pub = login?.publisher();
|
||||
if (pub) {
|
||||
const newTags = tags.filter((t) => !t.at(1)!.endsWith(`:${identifier}`));
|
||||
const newTags = tags.filter((t) => !t[1].endsWith(`:${identifier}`));
|
||||
const userCardsEv = await pub.generic((eb) => {
|
||||
eb.kind(USER_CARDS).content("");
|
||||
for (const tag of newTags) {
|
||||
@ -408,7 +408,7 @@ export function StreamCardEditor({ pubkey, tags }: StreamCardEditorProps) {
|
||||
<>
|
||||
<div className="stream-cards">
|
||||
{cards.map((ev) => (
|
||||
<Card canEdit={isEditing} cards={cards} key={ev.id} ev={ev!} />
|
||||
<Card canEdit={isEditing} cards={cards} key={ev.id} ev={ev} />
|
||||
))}
|
||||
{isEditing && <AddCard cards={cards} />}
|
||||
</div>
|
||||
@ -433,7 +433,7 @@ export function ReadOnlyStreamCards({ host }: StreamCardsProps) {
|
||||
return (
|
||||
<div className="stream-cards">
|
||||
{cards.map((ev) => (
|
||||
<Card cards={cards} key={ev!.id} ev={ev!} />
|
||||
<Card cards={cards} key={ev.id} ev={ev} />
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
|
@ -53,11 +53,11 @@ export function Textarea({ emojis, ...props }: TextareaProps) {
|
||||
const userDataProvider = async (token: string) => {
|
||||
const cache = System.ProfileLoader.Cache;
|
||||
if (cache instanceof UserProfileCache) {
|
||||
return cache.search(token);
|
||||
return await cache.search(token);
|
||||
}
|
||||
};
|
||||
|
||||
const emojiDataProvider = async (token: string) => {
|
||||
const emojiDataProvider = (token: string) => {
|
||||
const results = emojis
|
||||
.map((t) => {
|
||||
return {
|
||||
|
84
src/fonts/outfit/outfit.css
Normal file
84
src/fonts/outfit/outfit.css
Normal file
@ -0,0 +1,84 @@
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: "Outfit";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(outfit_400_latin-ext.woff2) format("woff2");
|
||||
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF,
|
||||
U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: "Outfit";
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
font-display: swap;
|
||||
src: url(outfit_400_latin.woff2) format("woff2");
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
|
||||
U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
|
||||
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: "Outfit";
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(outfit_500_latin-ext.woff2) format("woff2");
|
||||
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF,
|
||||
U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: "Outfit";
|
||||
font-style: normal;
|
||||
font-weight: 500;
|
||||
font-display: swap;
|
||||
src: url(outfit_500_latin.woff2) format("woff2");
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
|
||||
U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
|
||||
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: "Outfit";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(outfit_600_latin-ext.woff2) format("woff2");
|
||||
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF,
|
||||
U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: "Outfit";
|
||||
font-style: normal;
|
||||
font-weight: 600;
|
||||
font-display: swap;
|
||||
src: url(outfit_600_latin.woff2) format("woff2");
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
|
||||
U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
|
||||
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
||||
/* latin-ext */
|
||||
@font-face {
|
||||
font-family: "Outfit";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(outfit_700_latin-ext.woff2) format("woff2");
|
||||
unicode-range: U+0100-02AF, U+0304, U+0308, U+0329, U+1E00-1E9F, U+1EF2-1EFF,
|
||||
U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
|
||||
}
|
||||
/* latin */
|
||||
@font-face {
|
||||
font-family: "Outfit";
|
||||
font-style: normal;
|
||||
font-weight: 700;
|
||||
font-display: swap;
|
||||
src: url(outfit_700_latin.woff2) format("woff2");
|
||||
unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA,
|
||||
U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+2074, U+20AC, U+2122, U+2191,
|
||||
U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
|
||||
}
|
BIN
src/fonts/outfit/outfit_400_latin-ext.woff2
Normal file
BIN
src/fonts/outfit/outfit_400_latin-ext.woff2
Normal file
Binary file not shown.
BIN
src/fonts/outfit/outfit_400_latin.woff2
Normal file
BIN
src/fonts/outfit/outfit_400_latin.woff2
Normal file
Binary file not shown.
BIN
src/fonts/outfit/outfit_500_latin-ext.woff2
Normal file
BIN
src/fonts/outfit/outfit_500_latin-ext.woff2
Normal file
Binary file not shown.
BIN
src/fonts/outfit/outfit_500_latin.woff2
Normal file
BIN
src/fonts/outfit/outfit_500_latin.woff2
Normal file
Binary file not shown.
BIN
src/fonts/outfit/outfit_600_latin-ext.woff2
Normal file
BIN
src/fonts/outfit/outfit_600_latin-ext.woff2
Normal file
Binary file not shown.
BIN
src/fonts/outfit/outfit_600_latin.woff2
Normal file
BIN
src/fonts/outfit/outfit_600_latin.woff2
Normal file
Binary file not shown.
BIN
src/fonts/outfit/outfit_700_latin-ext.woff2
Normal file
BIN
src/fonts/outfit/outfit_700_latin-ext.woff2
Normal file
Binary file not shown.
BIN
src/fonts/outfit/outfit_700_latin.woff2
Normal file
BIN
src/fonts/outfit/outfit_700_latin.woff2
Normal file
Binary file not shown.
@ -29,7 +29,7 @@ export function useUserCards(
|
||||
|
||||
const subRelated = useMemo(() => {
|
||||
if (!pubkey) return null;
|
||||
const splitted = related.map((t) => t.at(1)!.split(":"));
|
||||
const splitted = related.map((t) => t[1].split(":"));
|
||||
const authors = splitted
|
||||
.map((s) => s.at(1))
|
||||
.filter((s) => s)
|
||||
@ -58,7 +58,7 @@ export function useUserCards(
|
||||
const cards = useMemo(() => {
|
||||
return related
|
||||
.map((t) => {
|
||||
const [k, pubkey, identifier] = t.at(1)!.split(":");
|
||||
const [k, pubkey, identifier] = t[1].split(":");
|
||||
const kind = Number(k);
|
||||
return (data ?? []).find(
|
||||
(e) =>
|
||||
@ -104,7 +104,7 @@ export function useCards(pubkey: string, leaveOpen = false): TaggedRawEvent[] {
|
||||
|
||||
const subRelated = useMemo(() => {
|
||||
if (!pubkey) return null;
|
||||
const splitted = related.map((t) => t.at(1)!.split(":"));
|
||||
const splitted = related.map((t) => t[1].split(":"));
|
||||
const authors = splitted
|
||||
.map((s) => s.at(1))
|
||||
.filter((s) => s)
|
||||
@ -134,7 +134,7 @@ export function useCards(pubkey: string, leaveOpen = false): TaggedRawEvent[] {
|
||||
const cards = useMemo(() => {
|
||||
return related
|
||||
.map((t) => {
|
||||
const [k, pubkey, identifier] = t.at(1)!.split(":");
|
||||
const [k, pubkey, identifier] = t[1].split(":");
|
||||
const kind = Number(k);
|
||||
return cardEvents.find(
|
||||
(e) =>
|
||||
|
@ -45,7 +45,7 @@ export function useUserEmojiPacks(pubkey?: string, userEmoji?: Tags) {
|
||||
|
||||
const subRelated = useMemo(() => {
|
||||
if (!pubkey) return null;
|
||||
const splitted = related.map((t) => t.at(1)!.split(":"));
|
||||
const splitted = related.map((t) => t[1].split(":"));
|
||||
const authors = splitted
|
||||
.map((s) => s.at(1))
|
||||
.filter((s) => s)
|
||||
|
@ -9,6 +9,7 @@ import {
|
||||
parseZap,
|
||||
} from "@snort/system";
|
||||
import { useRequestBuilder } from "@snort/system-react";
|
||||
import { unwrap } from "@snort/shared";
|
||||
import { GOAL } from "const";
|
||||
import { System } from "index";
|
||||
|
||||
@ -36,14 +37,15 @@ export function useZaps(goal: NostrEvent, leaveOpen = false) {
|
||||
);
|
||||
}
|
||||
|
||||
export function useZapGoal(host: string, link: NostrLink, leaveOpen = false) {
|
||||
export function useZapGoal(host: string, link?: NostrLink, leaveOpen = false) {
|
||||
const sub = useMemo(() => {
|
||||
if (!link) return null;
|
||||
const b = new RequestBuilder(`goals:${host.slice(0, 12)}`);
|
||||
b.withOptions({ leaveOpen });
|
||||
b.withFilter()
|
||||
.kinds([GOAL])
|
||||
.authors([host])
|
||||
.tag("a", [`${link.kind}:${link.author!}:${link.id}`]);
|
||||
.tag("a", [`${link.kind}:${unwrap(link.author)}:${link.id}`]);
|
||||
return b;
|
||||
}, [link, leaveOpen]);
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import "@szhsin/react-menu/dist/index.css";
|
||||
import "./index.css";
|
||||
import "./fonts/outfit/outfit.css";
|
||||
|
||||
import React from "react";
|
||||
import ReactDOM from "react-dom/client";
|
||||
@ -10,7 +11,7 @@ import { RootPage } from "pages/root";
|
||||
import { TagPage } from "pages/tag";
|
||||
import { LayoutPage } from "pages/layout";
|
||||
import { ProfilePage } from "pages/profile-page";
|
||||
import { StreamPage } from "pages/stream-page";
|
||||
import { StreamPageHandler } from "pages/stream-page";
|
||||
import { ChatPopout } from "pages/chat-popout";
|
||||
import { LoginStore } from "login";
|
||||
import { StreamProvidersPage } from "pages/providers";
|
||||
@ -53,7 +54,7 @@ const router = createBrowserRouter([
|
||||
},
|
||||
{
|
||||
path: "/:id",
|
||||
element: <StreamPage />,
|
||||
element: <StreamPageHandler />,
|
||||
},
|
||||
{
|
||||
path: "/providers/:id?",
|
||||
|
@ -1,6 +1,6 @@
|
||||
import { bytesToHex } from "@noble/curves/abstract/utils";
|
||||
import { schnorr } from "@noble/curves/secp256k1";
|
||||
import { ExternalStore } from "@snort/shared";
|
||||
import { ExternalStore, unwrap } from "@snort/shared";
|
||||
import { EventPublisher, Nip7Signer, PrivateKeySigner } from "@snort/system";
|
||||
import type { EmojiPack, Tags } from "types";
|
||||
|
||||
@ -131,7 +131,7 @@ export function getPublisher(session: LoginSession) {
|
||||
}
|
||||
case LoginType.PrivateKey: {
|
||||
return new EventPublisher(
|
||||
new PrivateKeySigner(session.privateKey!),
|
||||
new PrivateKeySigner(unwrap(session.privateKey)),
|
||||
session.pubkey
|
||||
);
|
||||
}
|
||||
|
@ -2,12 +2,13 @@ import "./chat-popout.css";
|
||||
import { LiveChat } from "element/live-chat";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { NostrPrefix, encodeTLV, parseNostrLink } from "@snort/system";
|
||||
import { unwrap } from "@snort/shared";
|
||||
import { useCurrentStreamFeed } from "hooks/current-stream-feed";
|
||||
import { findTag } from "utils";
|
||||
|
||||
export function ChatPopout() {
|
||||
const params = useParams();
|
||||
const link = parseNostrLink(params.id!);
|
||||
const link = parseNostrLink(unwrap(params.id));
|
||||
const ev = useCurrentStreamFeed(link, true);
|
||||
|
||||
const lnk = parseNostrLink(
|
||||
|
@ -10,6 +10,7 @@ import {
|
||||
encodeTLV,
|
||||
} from "@snort/system";
|
||||
import { useUserProfile } from "@snort/system-react";
|
||||
import { unwrap } from "@snort/shared";
|
||||
import { Profile } from "element/profile";
|
||||
import { Icon } from "element/icon";
|
||||
import { SendZapsDialog } from "element/send-zap";
|
||||
@ -52,7 +53,7 @@ const defaultBanner = "https://void.cat/d/Hn1AdN5UKmceuDkgDW847q.webp";
|
||||
export function ProfilePage() {
|
||||
const navigate = useNavigate();
|
||||
const params = useParams();
|
||||
const link = parseNostrLink(params.npub!);
|
||||
const link = parseNostrLink(unwrap(params.npub));
|
||||
const placeholder = usePlaceholder(link.id);
|
||||
const profile = useUserProfile(System, link.id);
|
||||
const zapTarget = profile?.lud16 ?? profile?.lud06;
|
||||
|
@ -1,5 +1,6 @@
|
||||
import "./stream-page.css";
|
||||
import { parseNostrLink, TaggedRawEvent } from "@snort/system";
|
||||
import { NostrLink, NostrPrefix, TaggedRawEvent, tryParseNostrLink } from "@snort/system";
|
||||
import { fetchNip05Pubkey } from "@snort/shared";
|
||||
import { useLocation, useNavigate, useParams } from "react-router-dom";
|
||||
import { Helmet } from "react-helmet";
|
||||
|
||||
@ -9,6 +10,7 @@ import {
|
||||
findTag,
|
||||
getEventFromLocationState,
|
||||
getHost,
|
||||
hexToBech32,
|
||||
} from "utils";
|
||||
import { Profile, getName } from "element/profile";
|
||||
import { LiveChat } from "element/live-chat";
|
||||
@ -31,6 +33,7 @@ import {
|
||||
isContentWarningAccepted,
|
||||
} from "element/content-warning";
|
||||
import { useCurrentStreamFeed } from "hooks/current-stream-feed";
|
||||
import { useEffect, useState } from "react";
|
||||
|
||||
function ProfileInfo({ ev, goal }: { ev?: NostrEvent; goal?: TaggedRawEvent }) {
|
||||
const login = useLogin();
|
||||
@ -110,14 +113,41 @@ function ProfileInfo({ ev, goal }: { ev?: NostrEvent; goal?: TaggedRawEvent }) {
|
||||
);
|
||||
}
|
||||
|
||||
export function StreamPage() {
|
||||
export function StreamPageHandler() {
|
||||
const params = useParams();
|
||||
const location = useLocation();
|
||||
const evPreload = getEventFromLocationState(location.state);
|
||||
const link = parseNostrLink(params.id!);
|
||||
const [link, setLink] = useState<NostrLink>();
|
||||
|
||||
useEffect(() => {
|
||||
if (params.id) {
|
||||
const parsedLink = tryParseNostrLink(params.id);
|
||||
if (parsedLink) {
|
||||
setLink(parsedLink);
|
||||
} else {
|
||||
const [handle, domain] = (params.id.includes("@") ? params.id : `${params.id}@zap.stream`).split("@");
|
||||
fetchNip05Pubkey(handle, domain).then(d => {
|
||||
if (d) {
|
||||
setLink({
|
||||
id: d,
|
||||
type: NostrPrefix.PublicKey,
|
||||
encode: () => hexToBech32(NostrPrefix.PublicKey, d)
|
||||
} as NostrLink);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}, [params.id]);
|
||||
|
||||
if (link) {
|
||||
return <StreamPage link={link} evPreload={evPreload} />
|
||||
}
|
||||
}
|
||||
|
||||
export function StreamPage({ link, evPreload }: { evPreload?: NostrEvent, link: NostrLink }) {
|
||||
const ev = useCurrentStreamFeed(link, true, evPreload);
|
||||
const host = getHost(ev);
|
||||
const goal = useZapGoal(host, link, true);
|
||||
const goal = useZapGoal(host, createNostrLink(ev), true);
|
||||
|
||||
const title = findTag(ev, "title");
|
||||
const summary = findTag(ev, "summary");
|
||||
|
@ -1,5 +1,6 @@
|
||||
import "./tag.css";
|
||||
import { useParams } from "react-router-dom";
|
||||
import { unwrap } from "@snort/shared";
|
||||
|
||||
import { VideoTile } from "element/video-tile";
|
||||
import { FollowTagButton } from "element/follow-button";
|
||||
@ -12,7 +13,7 @@ export function TagPage() {
|
||||
<div className="tag-page">
|
||||
<div className="tag-page-header">
|
||||
<h1>#{tag}</h1>
|
||||
<FollowTagButton tag={tag!} />
|
||||
<FollowTagButton tag={unwrap(tag)} />
|
||||
</div>
|
||||
<div className="video-grid">
|
||||
{live.map((e) => (
|
||||
|
@ -58,7 +58,7 @@ export class OwncastProvider implements StreamProvider {
|
||||
body?: unknown
|
||||
): Promise<T> {
|
||||
const rsp = await fetch(`${this.#url}${path}`, {
|
||||
method: method,
|
||||
method,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
|
@ -103,7 +103,7 @@ export class Nip103StreamProvider implements StreamProvider {
|
||||
.tag(["method", method]);
|
||||
});
|
||||
const rsp = await fetch(u, {
|
||||
method: method,
|
||||
method,
|
||||
body: body ? JSON.stringify(body) : undefined,
|
||||
headers: {
|
||||
"content-type": "application/json",
|
||||
|
@ -109,7 +109,7 @@ export function getHost(ev?: NostrEvent) {
|
||||
);
|
||||
}
|
||||
|
||||
export async function openFile(): Promise<File | undefined> {
|
||||
export function openFile(): Promise<File | undefined> {
|
||||
return new Promise((resolve) => {
|
||||
const elm = document.createElement("input");
|
||||
elm.type = "file";
|
||||
|
@ -503,7 +503,7 @@ export class WISH extends TypedEventTarget {
|
||||
},
|
||||
});
|
||||
const body = await resp.text();
|
||||
if (resp.status != 201) {
|
||||
if (resp.status !== 201) {
|
||||
throw new Error(`Unexpected status code ${resp.status}: ${body}`);
|
||||
}
|
||||
|
||||
@ -611,7 +611,7 @@ export class WISH extends TypedEventTarget {
|
||||
throw new Error(`Unexpected status code ${resp.status}: ${body}`);
|
||||
}
|
||||
|
||||
async WithEndpoint(endpoint: string, trickle: boolean) {
|
||||
WithEndpoint(endpoint: string, trickle: boolean) {
|
||||
if (endpoint === "") {
|
||||
throw new Error("Endpoint cannot be empty");
|
||||
}
|
||||
@ -637,7 +637,7 @@ export class WISH extends TypedEventTarget {
|
||||
method: "DELETE",
|
||||
mode: "cors",
|
||||
});
|
||||
if (resp.status != 200) {
|
||||
if (resp.status !== 200) {
|
||||
const body = await resp.text();
|
||||
throw new Error(`Unexpected status code ${resp.status}: ${body}`);
|
||||
}
|
||||
|
@ -68,8 +68,8 @@ const config = {
|
||||
}),
|
||||
new webpack.DefinePlugin({
|
||||
__XXX: process.env["__XXX"] || JSON.stringify(false),
|
||||
__XXX_HOST: JSON.stringify("https://xxzap.com")
|
||||
})
|
||||
__XXX_HOST: JSON.stringify("https://xxzap.com"),
|
||||
}),
|
||||
],
|
||||
module: {
|
||||
rules: [
|
||||
@ -89,9 +89,12 @@ const config = {
|
||||
babelrc: false,
|
||||
configFile: false,
|
||||
presets: [
|
||||
["@babel/preset-env", {
|
||||
targets: "defaults"
|
||||
}],
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{
|
||||
targets: "defaults",
|
||||
},
|
||||
],
|
||||
["@babel/preset-react", { runtime: "automatic" }],
|
||||
"@babel/preset-typescript",
|
||||
],
|
||||
@ -106,7 +109,7 @@ const config = {
|
||||
],
|
||||
},
|
||||
},
|
||||
require.resolve("ts-loader")
|
||||
require.resolve("ts-loader"),
|
||||
],
|
||||
},
|
||||
{
|
||||
@ -148,7 +151,7 @@ const config = {
|
||||
aliasFields: ["browser"],
|
||||
extensions: ["...", ".tsx", ".ts", ".jsx", ".js"],
|
||||
modules: ["...", __dirname, path.resolve(__dirname, "src")],
|
||||
fallback: { "crypto": false }
|
||||
fallback: { crypto: false },
|
||||
},
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user