You've already forked AstralRinth
forked from didirus/AstralRinth
9
.github/workflows/app-release.yml
vendored
9
.github/workflows/app-release.yml
vendored
@@ -42,9 +42,6 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
components: rustfmt, clippy
|
components: rustfmt, clippy
|
||||||
|
|
||||||
- name: Install Tauri CLI
|
|
||||||
run: cargo install tauri-cli --git https://github.com/modrinth/tauri.git --rev 5e2942876c2266594ed1db516c1d9975c873c36a
|
|
||||||
|
|
||||||
- name: Setup rust cache
|
- name: Setup rust cache
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
@@ -66,7 +63,7 @@ jobs:
|
|||||||
!target/release/bundle/msi/*.msi
|
!target/release/bundle/msi/*.msi
|
||||||
!target/release/bundle/msi/*.msi.zip
|
!target/release/bundle/msi/*.msi.zip
|
||||||
!target/release/bundle/msi/*.msi.zip.sig
|
!target/release/bundle/msi/*.msi.zip.sig
|
||||||
|
|
||||||
!target/release/bundle/nsis/*.exe
|
!target/release/bundle/nsis/*.exe
|
||||||
!target/release/bundle/nsis/*.nsis.zip
|
!target/release/bundle/nsis/*.nsis.zip
|
||||||
!target/release/bundle/nsis/*.nsis.zip.sig
|
!target/release/bundle/nsis/*.nsis.zip.sig
|
||||||
@@ -115,7 +112,6 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
V1_COMPATIBLE_BIN_NAME: true
|
|
||||||
|
|
||||||
- name: build app
|
- name: build app
|
||||||
run: pnpm --filter=@modrinth/app run tauri build --config "tauri-release.conf.json"
|
run: pnpm --filter=@modrinth/app run tauri build --config "tauri-release.conf.json"
|
||||||
@@ -125,7 +121,6 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
TAURI_SIGNING_PRIVATE_KEY: ${{ secrets.TAURI_PRIVATE_KEY }}
|
||||||
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
TAURI_SIGNING_PRIVATE_KEY_PASSWORD: ${{ secrets.TAURI_KEY_PASSWORD }}
|
||||||
V1_COMPATIBLE_BIN_NAME: true
|
|
||||||
|
|
||||||
- name: upload ${{ matrix.platform }}
|
- name: upload ${{ matrix.platform }}
|
||||||
uses: actions/upload-artifact@v4
|
uses: actions/upload-artifact@v4
|
||||||
@@ -148,7 +143,7 @@ jobs:
|
|||||||
target/release/bundle/msi/*.msi
|
target/release/bundle/msi/*.msi
|
||||||
target/release/bundle/msi/*.msi.zip
|
target/release/bundle/msi/*.msi.zip
|
||||||
target/release/bundle/msi/*.msi.zip.sig
|
target/release/bundle/msi/*.msi.zip.sig
|
||||||
|
|
||||||
target/release/bundle/nsis/*.exe
|
target/release/bundle/nsis/*.exe
|
||||||
target/release/bundle/nsis/*.nsis.zip
|
target/release/bundle/nsis/*.nsis.zip
|
||||||
target/release/bundle/nsis/*.nsis.zip.sig
|
target/release/bundle/nsis/*.nsis.zip.sig
|
||||||
|
|||||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -55,3 +55,6 @@ generated
|
|||||||
|
|
||||||
# app testing dir
|
# app testing dir
|
||||||
app-playground-data/*
|
app-playground-data/*
|
||||||
|
|
||||||
|
Cargo.lock
|
||||||
|
pnpm-lock.yaml
|
||||||
741
Cargo.lock
generated
741
Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -18,5 +18,4 @@ strip = true # Remove debug symbols
|
|||||||
opt-level = 3
|
opt-level = 3
|
||||||
|
|
||||||
[patch.crates-io]
|
[patch.crates-io]
|
||||||
wry = { git = "https://github.com/modrinth/wry", rev = "5840108" }
|
wry = { git = "https://github.com/modrinth/wry", rev = "27fb16b" }
|
||||||
tauri = { git = "https://github.com/modrinth/tauri", rev = "5e29428" }
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@modrinth/app-frontend",
|
"name": "@modrinth/app-frontend",
|
||||||
"private": true,
|
"private": true,
|
||||||
"version": "0.8.701",
|
"version": "0.8.801",
|
||||||
"development_build": true,
|
"development_build": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ async function repairInstance() {
|
|||||||
</p>
|
</p>
|
||||||
<p>You may be able to fix it through one of the following ways:</p>
|
<p>You may be able to fix it through one of the following ways:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Ennsuring you are connected to the internet, then try restarting the app.</li>
|
<li>Ensuring you are connected to the internet, then try restarting the app.</li>
|
||||||
<li>Redownloading the app.</li>
|
<li>Redownloading the app.</li>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ const createInstance = async () => {
|
|||||||
@click="installModal.hide()"
|
@click="installModal.hide()"
|
||||||
>
|
>
|
||||||
<Avatar
|
<Avatar
|
||||||
:src="profile.icon_path ? tauri.convertFileSrc(profile.icon_path) : null"
|
:src="profile.icon_path ? convertFileSrc(profile.icon_path) : null"
|
||||||
class="profile-image"
|
class="profile-image"
|
||||||
/>
|
/>
|
||||||
{{ profile.name }}
|
{{ profile.name }}
|
||||||
|
|||||||
@@ -319,6 +319,25 @@ await getBranches()
|
|||||||
<span class="label__title size-card-header">Privacy</span>
|
<span class="label__title size-card-header">Privacy</span>
|
||||||
</h3>
|
</h3>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="adjacent-input">
|
||||||
|
<label for="opt-out-analytics">
|
||||||
|
<span class="label__title">Personalized ads</span>
|
||||||
|
<span class="label__description">
|
||||||
|
Modrinth's ad provider, Aditude, shows ads based on your preferences. By disabling this
|
||||||
|
option, you opt out and ads will no longer be shown based on your interests.
|
||||||
|
</span>
|
||||||
|
</label>
|
||||||
|
<Toggle
|
||||||
|
id="opt-out-analytics"
|
||||||
|
:model-value="settings.personalized_ads"
|
||||||
|
:checked="settings.personalized_ads"
|
||||||
|
@update:model-value="
|
||||||
|
(e) => {
|
||||||
|
settings.personalized_ads = e
|
||||||
|
}
|
||||||
|
"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<div class="adjacent-input">
|
<div class="adjacent-input">
|
||||||
<label for="opt-out-analytics">
|
<label for="opt-out-analytics">
|
||||||
<span class="label__title">Telemetry</span>
|
<span class="label__title">Telemetry</span>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "theseus_gui"
|
name = "theseus_gui"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
description = "The Modrinth App is a desktop application for managing your Minecraft mods"
|
description = "The Modrinth App is a desktop application for managing your Minecraft mods"
|
||||||
license = "GPL-3.0-only"
|
license = "GPL-3.0-only"
|
||||||
repository = "https://github.com/modrinth/code/apps/app/"
|
repository = "https://github.com/modrinth/code/apps/app/"
|
||||||
@@ -8,7 +8,7 @@ edition = "2021"
|
|||||||
build = "build.rs"
|
build = "build.rs"
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
tauri-build = { git = "https://github.com/modrinth/tauri", features = ["codegen"], rev = "5e29428" }
|
tauri-build = { version = "2.0.0-rc", features = ["codegen"] }
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
theseus = { path = "../../packages/app-lib", features = ["tauri"] }
|
theseus = { path = "../../packages/app-lib", features = ["tauri"] }
|
||||||
@@ -16,7 +16,7 @@ theseus = { path = "../../packages/app-lib", features = ["tauri"] }
|
|||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
|
||||||
tauri = { git = "https://github.com/modrinth/tauri", features = ["devtools", "macos-private-api", "protocol-asset", "unstable"], rev = "5e29428" }
|
tauri = { version = "2.0.0-rc", features = ["devtools", "macos-private-api", "protocol-asset", "unstable"] }
|
||||||
tauri-plugin-window-state = "2.0.0-rc"
|
tauri-plugin-window-state = "2.0.0-rc"
|
||||||
tauri-plugin-deep-link = "2.0.0-rc"
|
tauri-plugin-deep-link = "2.0.0-rc"
|
||||||
tauri-plugin-os = "2.0.0-rc"
|
tauri-plugin-os = "2.0.0-rc"
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ Before you begin, ensure you have the following installed on your machine:
|
|||||||
Follow these steps to set up your development environment:
|
Follow these steps to set up your development environment:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
cargo install tauri-cli --git https://github.com/modrinth/tauri.git --rev 5e2942876c2266594ed1db516c1d9975c873c36a
|
|
||||||
pnpm install
|
pnpm install
|
||||||
pnpm app:dev
|
pnpm app:dev
|
||||||
```
|
```
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,346 +0,0 @@
|
|||||||
<?if $(sys.BUILDARCH)="x86"?>
|
|
||||||
<?define Win64 = "no" ?>
|
|
||||||
<?define PlatformProgramFilesFolder = "ProgramFilesFolder" ?>
|
|
||||||
<?elseif $(sys.BUILDARCH)="x64"?>
|
|
||||||
<?define Win64 = "yes" ?>
|
|
||||||
<?define PlatformProgramFilesFolder = "ProgramFiles64Folder" ?>
|
|
||||||
<?else?>
|
|
||||||
<?error Unsupported value of sys.BUILDARCH=$(sys.BUILDARCH)?>
|
|
||||||
<?endif?>
|
|
||||||
|
|
||||||
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
|
||||||
<Product
|
|
||||||
Id="*"
|
|
||||||
Name="{{product_name}}"
|
|
||||||
UpgradeCode="{{upgrade_code}}"
|
|
||||||
Language="!(loc.TauriLanguage)"
|
|
||||||
Manufacturer="{{manufacturer}}"
|
|
||||||
Version="{{version}}">
|
|
||||||
|
|
||||||
<Package Id="*"
|
|
||||||
Keywords="Installer"
|
|
||||||
InstallerVersion="450"
|
|
||||||
Languages="0"
|
|
||||||
Compressed="yes"
|
|
||||||
InstallScope="perMachine"
|
|
||||||
SummaryCodepage="!(loc.TauriCodepage)"/>
|
|
||||||
|
|
||||||
<!-- https://docs.microsoft.com/en-us/windows/win32/msi/reinstallmode -->
|
|
||||||
<!-- reinstall all files; rewrite all registry entries; reinstall all shortcuts -->
|
|
||||||
<Property Id="REINSTALLMODE" Value="amus" />
|
|
||||||
|
|
||||||
{{#if allow_downgrades}}
|
|
||||||
<MajorUpgrade Schedule="afterInstallInitialize" AllowDowngrades="yes" />
|
|
||||||
{{else}}
|
|
||||||
<MajorUpgrade Schedule="afterInstallInitialize" DowngradeErrorMessage="!(loc.DowngradeErrorMessage)" AllowSameVersionUpgrades="yes" />
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<InstallExecuteSequence>
|
|
||||||
<RemoveShortcuts>Installed AND NOT UPGRADINGPRODUCTCODE</RemoveShortcuts>
|
|
||||||
</InstallExecuteSequence>
|
|
||||||
|
|
||||||
<Media Id="1" Cabinet="app.cab" EmbedCab="yes" />
|
|
||||||
|
|
||||||
{{#if banner_path}}
|
|
||||||
<WixVariable Id="WixUIBannerBmp" Value="{{banner_path}}" />
|
|
||||||
{{/if}}
|
|
||||||
{{#if dialog_image_path}}
|
|
||||||
<WixVariable Id="WixUIDialogBmp" Value="{{dialog_image_path}}" />
|
|
||||||
{{/if}}
|
|
||||||
{{#if license}}
|
|
||||||
<WixVariable Id="WixUILicenseRtf" Value="{{license}}" />
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<Icon Id="ProductIcon" SourceFile="{{icon_path}}"/>
|
|
||||||
<Property Id="ARPPRODUCTICON" Value="ProductIcon" />
|
|
||||||
<Property Id="ARPNOREPAIR" Value="yes" Secure="yes" /> <!-- Remove repair -->
|
|
||||||
<SetProperty Id="ARPNOMODIFY" Value="1" After="InstallValidate" Sequence="execute"/>
|
|
||||||
|
|
||||||
<!-- initialize with previous InstallDir -->
|
|
||||||
<Property Id="INSTALLDIR">
|
|
||||||
<RegistrySearch Id="PrevInstallDirReg" Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}" Name="InstallDir" Type="raw"/>
|
|
||||||
</Property>
|
|
||||||
|
|
||||||
<!-- launch app checkbox -->
|
|
||||||
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOXTEXT" Value="!(loc.LaunchApp)" />
|
|
||||||
<Property Id="WIXUI_EXITDIALOGOPTIONALCHECKBOX" Value="1"/>
|
|
||||||
<Property Id="WixShellExecTarget" Value="[!Path]" />
|
|
||||||
<CustomAction Id="LaunchApplication" BinaryKey="WixCA" DllEntry="WixShellExec" Impersonate="yes" />
|
|
||||||
|
|
||||||
<UI>
|
|
||||||
<!-- launch app checkbox -->
|
|
||||||
<Publish Dialog="ExitDialog" Control="Finish" Event="DoAction" Value="LaunchApplication">WIXUI_EXITDIALOGOPTIONALCHECKBOX = 1 and NOT Installed</Publish>
|
|
||||||
|
|
||||||
<Property Id="WIXUI_INSTALLDIR" Value="INSTALLDIR" />
|
|
||||||
|
|
||||||
{{#unless license}}
|
|
||||||
<!-- Skip license dialog -->
|
|
||||||
<Publish Dialog="WelcomeDlg"
|
|
||||||
Control="Next"
|
|
||||||
Event="NewDialog"
|
|
||||||
Value="InstallDirDlg"
|
|
||||||
Order="2">1</Publish>
|
|
||||||
<Publish Dialog="InstallDirDlg"
|
|
||||||
Control="Back"
|
|
||||||
Event="NewDialog"
|
|
||||||
Value="WelcomeDlg"
|
|
||||||
Order="2">1</Publish>
|
|
||||||
{{/unless}}
|
|
||||||
</UI>
|
|
||||||
|
|
||||||
<UIRef Id="WixUI_InstallDir" />
|
|
||||||
|
|
||||||
<Directory Id="TARGETDIR" Name="SourceDir">
|
|
||||||
<Directory Id="DesktopFolder" Name="Desktop">
|
|
||||||
<Component Id="ApplicationShortcutDesktop" Guid="*">
|
|
||||||
<Shortcut Id="ApplicationDesktopShortcut" Name="{{product_name}}" Description="Runs {{product_name}}" Target="[!Path]" WorkingDirectory="INSTALLDIR" />
|
|
||||||
<RemoveFolder Id="DesktopFolder" On="uninstall" />
|
|
||||||
<RegistryValue Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}" Name="Desktop Shortcut" Type="integer" Value="1" KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
</Directory>
|
|
||||||
<Directory Id="$(var.PlatformProgramFilesFolder)" Name="PFiles">
|
|
||||||
<Directory Id="INSTALLDIR" Name="{{product_name}}"/>
|
|
||||||
</Directory>
|
|
||||||
<Directory Id="ProgramMenuFolder">
|
|
||||||
<Directory Id="ApplicationProgramsFolder" Name="{{product_name}}"/>
|
|
||||||
</Directory>
|
|
||||||
</Directory>
|
|
||||||
|
|
||||||
<DirectoryRef Id="INSTALLDIR">
|
|
||||||
<Component Id="RegistryEntries" Guid="*">
|
|
||||||
<RegistryKey Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}">
|
|
||||||
<RegistryValue Name="InstallDir" Type="string" Value="[INSTALLDIR]" KeyPath="yes" />
|
|
||||||
</RegistryKey>
|
|
||||||
</Component>
|
|
||||||
|
|
||||||
<Component Id="Path" Guid="{{path_component_guid}}" Win64="$(var.Win64)">
|
|
||||||
<File Id="Path" Source="{{app_exe_source}}" KeyPath="yes" Checksum="yes"/>
|
|
||||||
<!-- THESEUS -->
|
|
||||||
<ProgId Id="theseus.mrpack.Document" Description="Modrinth File">
|
|
||||||
<Extension Id="mrpack" ContentType="application/mrpack">
|
|
||||||
<!-- no flags on argument, so we can hijack deep link library-->
|
|
||||||
<Verb Id="open" Command="Open" TargetFile="Path" Argument=""%1"" />
|
|
||||||
</Extension>
|
|
||||||
</ProgId>
|
|
||||||
<!-- /THESEUS -->
|
|
||||||
</Component>
|
|
||||||
{{#each binaries as |bin| ~}}
|
|
||||||
<Component Id="{{ bin.id }}" Guid="{{bin.guid}}" Win64="$(var.Win64)">
|
|
||||||
<File Id="Bin_{{ bin.id }}" Source="{{bin.path}}" KeyPath="yes"/>
|
|
||||||
</Component>
|
|
||||||
{{/each~}}
|
|
||||||
{{#if enable_elevated_update_task}}
|
|
||||||
<Component Id="UpdateTask" Guid="C492327D-9720-4CD5-8DB8-F09082AF44BE" Win64="$(var.Win64)">
|
|
||||||
<File Id="UpdateTask" Source="update.xml" KeyPath="yes" Checksum="yes"/>
|
|
||||||
</Component>
|
|
||||||
<Component Id="UpdateTaskInstaller" Guid="011F25ED-9BE3-50A7-9E9B-3519ED2B9932" Win64="$(var.Win64)">
|
|
||||||
<File Id="UpdateTaskInstaller" Source="install-task.ps1" KeyPath="yes" Checksum="yes"/>
|
|
||||||
</Component>
|
|
||||||
<Component Id="UpdateTaskUninstaller" Guid="D4F6CC3F-32DC-5FD0-95E8-782FFD7BBCE1" Win64="$(var.Win64)">
|
|
||||||
<File Id="UpdateTaskUninstaller" Source="uninstall-task.ps1" KeyPath="yes" Checksum="yes"/>
|
|
||||||
</Component>
|
|
||||||
{{/if}}
|
|
||||||
{{resources}}
|
|
||||||
<Component Id="CMP_UninstallShortcut" Guid="*">
|
|
||||||
|
|
||||||
<Shortcut Id="UninstallShortcut"
|
|
||||||
Name="Uninstall {{product_name}}"
|
|
||||||
Description="Uninstalls {{product_name}}"
|
|
||||||
Target="[System64Folder]msiexec.exe"
|
|
||||||
Arguments="/x [ProductCode]" />
|
|
||||||
|
|
||||||
<RemoveFolder Id="INSTALLDIR"
|
|
||||||
On="uninstall" />
|
|
||||||
|
|
||||||
<RegistryValue Root="HKCU"
|
|
||||||
Key="Software\\{{manufacturer}}\\{{product_name}}"
|
|
||||||
Name="Uninstaller Shortcut"
|
|
||||||
Type="integer"
|
|
||||||
Value="1"
|
|
||||||
KeyPath="yes" />
|
|
||||||
</Component>
|
|
||||||
|
|
||||||
<!-- THESEUS -->
|
|
||||||
<Component Id="FileTypeAssociationsReg" Guid="*">
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\modrinth\theseus\Capabilities" Name="ApplicationDescription" Value="theseus" Type="string" />
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\modrinth\theseus\Capabilities" Name="ApplicationIcon" Value="[INSTALLDIR]theseus,0" Type="string" />
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\modrinth\theseus\Capabilities" Name="ApplicationName" Value="theseus" Type="string" />
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\modrinth\theseus\Capabilities\DefaultIcon" Value="[INSTALLDIR]theseus,1" Type="string" />
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\modrinth\theseus\Capabilities\FileAssociations" Name=".mrpack" Value="theseus.mrpack.Document" Type="string" />
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\modrinth\theseus\Capabilities\MIMEAssociations" Name="application/mrpack" Value="theseus.mrpack.Document" Type="string" />
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\modrinth\theseus\Capabilities\shell\Open\command" Value=""[INSTALLDIR]theseus" -e "%1"" Type="string" />
|
|
||||||
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\RegisteredApplications" Name="theseus" Value="SOFTWARE\modrinth\theseus\Capabilities" Type="string" KeyPath="yes" />
|
|
||||||
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\theseus.mrpack.Document" Name="MRPACK File" Value="Modrinth Modpack Installer" Type="string" />
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\.mrpack" Name="Content Type" Value="application/mrpack" Type="string" />
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\.mrpack\OpenWithList\theseus" Value="" Type="string" />
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\.mrpack\OpenWithProgids" Name="theseus.mrpack.Document" Value="" Type="string" />
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\Applications\mrpack\SupportedTypes" Name=".mrpack" Value="" Type="string" />
|
|
||||||
<RegistryValue Root="HKLM" Key="SOFTWARE\Classes\Applications\mrpack\shell\open" Name="FriendlyAppName" Value="theseus" Type="string" />
|
|
||||||
</Component>
|
|
||||||
<!-- /THESEUS -->
|
|
||||||
|
|
||||||
</DirectoryRef>
|
|
||||||
|
|
||||||
<DirectoryRef Id="ApplicationProgramsFolder">
|
|
||||||
<Component Id="ApplicationShortcut" Guid="*">
|
|
||||||
<Shortcut Id="ApplicationStartMenuShortcut"
|
|
||||||
Name="{{product_name}}"
|
|
||||||
Description="Runs {{product_name}}"
|
|
||||||
Target="[!Path]"
|
|
||||||
Icon="ProductIcon"
|
|
||||||
WorkingDirectory="INSTALLDIR">
|
|
||||||
<ShortcutProperty Key="System.AppUserModel.ID" Value="{{bundle_id}}"/>
|
|
||||||
</Shortcut>
|
|
||||||
<RemoveFolder Id="ApplicationProgramsFolder" On="uninstall"/>
|
|
||||||
<RegistryValue Root="HKCU" Key="Software\\{{manufacturer}}\\{{product_name}}" Name="Start Menu Shortcut" Type="integer" Value="1" KeyPath="yes"/>
|
|
||||||
</Component>
|
|
||||||
</DirectoryRef>
|
|
||||||
|
|
||||||
{{#each merge_modules as |msm| ~}}
|
|
||||||
<DirectoryRef Id="TARGETDIR">
|
|
||||||
<Merge Id="{{ msm.name }}" SourceFile="{{ msm.path }}" DiskId="1" Language="!(loc.TauriLanguage)" />
|
|
||||||
</DirectoryRef>
|
|
||||||
|
|
||||||
<Feature Id="{{ msm.name }}" Title="{{ msm.name }}" AllowAdvertise="no" Display="hidden" Level="1">
|
|
||||||
<MergeRef Id="{{ msm.name }}"/>
|
|
||||||
</Feature>
|
|
||||||
{{/each~}}
|
|
||||||
|
|
||||||
<Feature
|
|
||||||
Id="MainProgram"
|
|
||||||
Title="Application"
|
|
||||||
Description="!(loc.InstallAppFeature)"
|
|
||||||
Level="1"
|
|
||||||
ConfigurableDirectory="INSTALLDIR"
|
|
||||||
AllowAdvertise="no"
|
|
||||||
Display="expand"
|
|
||||||
Absent="disallow">
|
|
||||||
|
|
||||||
<ComponentRef Id="RegistryEntries"/>
|
|
||||||
|
|
||||||
<!-- THESEUS -->
|
|
||||||
<ComponentRef Id="FileTypeAssociationsReg" />
|
|
||||||
<!-- /THESEUS -->
|
|
||||||
|
|
||||||
{{#each resource_file_ids as |resource_file_id| ~}}
|
|
||||||
<ComponentRef Id="{{ resource_file_id }}"/>
|
|
||||||
{{/each~}}
|
|
||||||
|
|
||||||
{{#if enable_elevated_update_task}}
|
|
||||||
<ComponentRef Id="UpdateTask" />
|
|
||||||
<ComponentRef Id="UpdateTaskInstaller" />
|
|
||||||
<ComponentRef Id="UpdateTaskUninstaller" />
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<Feature Id="ShortcutsFeature"
|
|
||||||
Title="Shortcuts"
|
|
||||||
Level="1">
|
|
||||||
<ComponentRef Id="Path"/>
|
|
||||||
<ComponentRef Id="CMP_UninstallShortcut" />
|
|
||||||
<ComponentRef Id="ApplicationShortcut" />
|
|
||||||
<ComponentRef Id="ApplicationShortcutDesktop" />
|
|
||||||
</Feature>
|
|
||||||
|
|
||||||
<Feature
|
|
||||||
Id="Environment"
|
|
||||||
Title="PATH Environment Variable"
|
|
||||||
Description="!(loc.PathEnvVarFeature)"
|
|
||||||
Level="1"
|
|
||||||
Absent="allow">
|
|
||||||
<ComponentRef Id="Path"/>
|
|
||||||
{{#each binaries as |bin| ~}}
|
|
||||||
<ComponentRef Id="{{ bin.id }}"/>
|
|
||||||
{{/each~}}
|
|
||||||
</Feature>
|
|
||||||
</Feature>
|
|
||||||
|
|
||||||
<Feature Id="External" AllowAdvertise="no" Absent="disallow">
|
|
||||||
{{#each component_group_refs as |id| ~}}
|
|
||||||
<ComponentGroupRef Id="{{ id }}"/>
|
|
||||||
{{/each~}}
|
|
||||||
{{#each component_refs as |id| ~}}
|
|
||||||
<ComponentRef Id="{{ id }}"/>
|
|
||||||
{{/each~}}
|
|
||||||
{{#each feature_group_refs as |id| ~}}
|
|
||||||
<FeatureGroupRef Id="{{ id }}"/>
|
|
||||||
{{/each~}}
|
|
||||||
{{#each feature_refs as |id| ~}}
|
|
||||||
<FeatureRef Id="{{ id }}"/>
|
|
||||||
{{/each~}}
|
|
||||||
{{#each merge_refs as |id| ~}}
|
|
||||||
<MergeRef Id="{{ id }}"/>
|
|
||||||
{{/each~}}
|
|
||||||
</Feature>
|
|
||||||
|
|
||||||
{{#if install_webview}}
|
|
||||||
<!-- WebView2 -->
|
|
||||||
<Property Id="WVRTINSTALLED">
|
|
||||||
<RegistrySearch Id="WVRTInstalledSystem" Root="HKLM" Key="SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Name="pv" Type="raw" Win64="no" />
|
|
||||||
<RegistrySearch Id="WVRTInstalledUser" Root="HKCU" Key="SOFTWARE\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" Name="pv" Type="raw"/>
|
|
||||||
</Property>
|
|
||||||
|
|
||||||
{{#if download_bootstrapper}}
|
|
||||||
<CustomAction Id='DownloadAndInvokeBootstrapper' Directory="INSTALLDIR" Execute="deferred" ExeCommand='powershell.exe -NoProfile -windowstyle hidden try [\{] [\[]Net.ServicePointManager[\]]::SecurityProtocol = [\[]Net.SecurityProtocolType[\]]::Tls12 [\}] catch [\{][\}]; Invoke-WebRequest -Uri "https://go.microsoft.com/fwlink/p/?LinkId=2124703" -OutFile "$env:TEMP\MicrosoftEdgeWebview2Setup.exe" ; Start-Process -FilePath "$env:TEMP\MicrosoftEdgeWebview2Setup.exe" -ArgumentList ({{webview_installer_args}} '/install') -Wait' Return='check'/>
|
|
||||||
<InstallExecuteSequence>
|
|
||||||
<Custom Action='DownloadAndInvokeBootstrapper' Before='InstallFinalize'>
|
|
||||||
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
|
|
||||||
</Custom>
|
|
||||||
</InstallExecuteSequence>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<!-- Embedded webview bootstrapper mode -->
|
|
||||||
{{#if webview2_bootstrapper_path}}
|
|
||||||
<Binary Id="MicrosoftEdgeWebview2Setup.exe" SourceFile="{{webview2_bootstrapper_path}}"/>
|
|
||||||
<CustomAction Id='InvokeBootstrapper' BinaryKey='MicrosoftEdgeWebview2Setup.exe' Execute="deferred" ExeCommand='{{webview_installer_args}} /install' Return='check' />
|
|
||||||
<InstallExecuteSequence>
|
|
||||||
<Custom Action='InvokeBootstrapper' Before='InstallFinalize'>
|
|
||||||
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
|
|
||||||
</Custom>
|
|
||||||
</InstallExecuteSequence>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<!-- Embedded offline installer -->
|
|
||||||
{{#if webview2_installer_path}}
|
|
||||||
<Binary Id="MicrosoftEdgeWebView2RuntimeInstaller.exe" SourceFile="{{webview2_installer_path}}"/>
|
|
||||||
<CustomAction Id='InvokeStandalone' BinaryKey='MicrosoftEdgeWebView2RuntimeInstaller.exe' Execute="deferred" ExeCommand='{{webview_installer_args}} /install' Return='check' />
|
|
||||||
<InstallExecuteSequence>
|
|
||||||
<Custom Action='InvokeStandalone' Before='InstallFinalize'>
|
|
||||||
<![CDATA[NOT(REMOVE OR WVRTINSTALLED)]]>
|
|
||||||
</Custom>
|
|
||||||
</InstallExecuteSequence>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
{{#if enable_elevated_update_task}}
|
|
||||||
<!-- Install an elevated update task within Windows Task Scheduler -->
|
|
||||||
<CustomAction
|
|
||||||
Id="CreateUpdateTask"
|
|
||||||
Return="check"
|
|
||||||
Directory="INSTALLDIR"
|
|
||||||
Execute="commit"
|
|
||||||
Impersonate="yes"
|
|
||||||
ExeCommand="powershell.exe -WindowStyle hidden .\install-task.ps1" />
|
|
||||||
<InstallExecuteSequence>
|
|
||||||
<Custom Action='CreateUpdateTask' Before='InstallFinalize'>
|
|
||||||
NOT(REMOVE)
|
|
||||||
</Custom>
|
|
||||||
</InstallExecuteSequence>
|
|
||||||
<!-- Remove elevated update task during uninstall -->
|
|
||||||
<CustomAction
|
|
||||||
Id="DeleteUpdateTask"
|
|
||||||
Return="check"
|
|
||||||
Directory="INSTALLDIR"
|
|
||||||
ExeCommand="powershell.exe -WindowStyle hidden .\uninstall-task.ps1" />
|
|
||||||
<InstallExecuteSequence>
|
|
||||||
<Custom Action="DeleteUpdateTask" Before='InstallFinalize'>
|
|
||||||
(REMOVE = "ALL") AND NOT UPGRADINGPRODUCTCODE
|
|
||||||
</Custom>
|
|
||||||
</InstallExecuteSequence>
|
|
||||||
{{/if}}
|
|
||||||
|
|
||||||
<SetProperty Id="ARPINSTALLLOCATION" Value="[INSTALLDIR]" After="CostFinalize"/>
|
|
||||||
</Product>
|
|
||||||
</Wix>
|
|
||||||
@@ -1,13 +1,16 @@
|
|||||||
{
|
{
|
||||||
"name": "@modrinth/app",
|
"name": "@modrinth/app",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build": "cargo tauri build",
|
"build": "tauri build",
|
||||||
"tauri": "cargo tauri",
|
"tauri": "tauri",
|
||||||
"dev": "cargo tauri dev",
|
"dev": "tauri dev",
|
||||||
"test": "cargo test",
|
"test": "cargo test",
|
||||||
"lint": "cargo fmt --check && cargo clippy -- -D warnings",
|
"lint": "cargo fmt --check && cargo clippy -- -D warnings",
|
||||||
"fix": "cargo fmt && cargo clippy --fix"
|
"fix": "cargo fmt && cargo clippy --fix"
|
||||||
},
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@tauri-apps/cli": "2.0.0-rc.16"
|
||||||
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@modrinth/app-frontend": "workspace:*",
|
"@modrinth/app-frontend": "workspace:*",
|
||||||
"@modrinth/app-lib": "workspace:*"
|
"@modrinth/app-lib": "workspace:*"
|
||||||
|
|||||||
@@ -21,9 +21,6 @@
|
|||||||
"certificateThumbprint": null,
|
"certificateThumbprint": null,
|
||||||
"digestAlgorithm": "sha256",
|
"digestAlgorithm": "sha256",
|
||||||
"timestampUrl": "http://timestamp.digicert.com",
|
"timestampUrl": "http://timestamp.digicert.com",
|
||||||
"wix": {
|
|
||||||
"template": "./msi/main.wxs"
|
|
||||||
},
|
|
||||||
"nsis": {
|
"nsis": {
|
||||||
"installMode": "perMachine",
|
"installMode": "perMachine",
|
||||||
"installerHooks": "./nsis/hooks.nsi"
|
"installerHooks": "./nsis/hooks.nsi"
|
||||||
@@ -52,8 +49,9 @@
|
|||||||
]
|
]
|
||||||
},
|
},
|
||||||
"productName": "AstralRinth App",
|
"productName": "AstralRinth App",
|
||||||
"version": "0.8.7",
|
"version": "0.8.8",
|
||||||
"identifier": "AstralRinthApp",
|
"identifier": "AstralRinthApp",
|
||||||
|
"mainBinaryName": "AstralRinth App",
|
||||||
"plugins": {
|
"plugins": {
|
||||||
"deep-link": {
|
"deep-link": {
|
||||||
"desktop": {
|
"desktop": {
|
||||||
|
|||||||
3
apps/app/tauri.linux.conf.json
Normal file
3
apps/app/tauri.linux.conf.json
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"mainBinaryName": "ModrinthApp"
|
||||||
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="ad-parent relative mb-3 flex w-full justify-center rounded-2xl bg-bg-raised">
|
<div class="ad-parent relative mb-3 flex w-full justify-center rounded-2xl bg-bg-raised">
|
||||||
<div class="flex max-h-[250px] min-h-[250px] min-w-[300px] max-w-[300px] flex-col gap-4 p-6">
|
<div class="flex max-h-[250px] min-h-[250px] min-w-[300px] max-w-[300px] flex-col gap-4 p-6">
|
||||||
<p class="m-0 text-2xl font-bold text-contrast">90% of ad revenue goes to creators</p>
|
<p class="m-0 text-2xl font-bold text-contrast">75% of ad revenue goes to creators</p>
|
||||||
<nuxt-link to="/plus" class="mt-auto items-center gap-1 text-purple hover:underline">
|
<nuxt-link to="/plus" class="mt-auto items-center gap-1 text-purple hover:underline">
|
||||||
<span>
|
<span>
|
||||||
Support creators and Modrinth ad-free with
|
Support creators and Modrinth ad-free with
|
||||||
@@ -28,6 +28,10 @@ useHead({
|
|||||||
"data-domain": "modrinth.com",
|
"data-domain": "modrinth.com",
|
||||||
async: true,
|
async: true,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
src: "https://bservr.com/o.js?uid=8118d1fdb2e0d6f32180bd27",
|
||||||
|
async: true,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
src: "/inmobi.js",
|
src: "/inmobi.js",
|
||||||
async: true,
|
async: true,
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ export function createDisplayNames(
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
return dict.of(lookup);
|
return dict.of(lookup);
|
||||||
} catch (err) {
|
} catch {
|
||||||
console.warn(
|
console.warn(
|
||||||
`Failed to get display name for ${lookup} using dictionary for ${
|
`Failed to get display name for ${lookup} using dictionary for ${
|
||||||
this.resolvedOptions().locale
|
this.resolvedOptions().locale
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import hljs from "highlight.js/lib/core";
|
import hljs from "highlight.js/lib/core";
|
||||||
// Scripting
|
// Scripting
|
||||||
import javascript from "highlight.js/lib/languages/javascript";
|
import javascript from "highlight.js/lib/languages/javascript";
|
||||||
import python from "highlight.js/lib/languages/python";
|
|
||||||
import lua from "highlight.js/lib/languages/lua";
|
import lua from "highlight.js/lib/languages/lua";
|
||||||
|
import python from "highlight.js/lib/languages/python";
|
||||||
// Coding
|
// Coding
|
||||||
|
import groovy from "highlight.js/lib/languages/groovy";
|
||||||
import java from "highlight.js/lib/languages/java";
|
import java from "highlight.js/lib/languages/java";
|
||||||
import kotlin from "highlight.js/lib/languages/kotlin";
|
import kotlin from "highlight.js/lib/languages/kotlin";
|
||||||
import scala from "highlight.js/lib/languages/scala";
|
import scala from "highlight.js/lib/languages/scala";
|
||||||
import groovy from "highlight.js/lib/languages/groovy";
|
|
||||||
// Configs
|
// Configs
|
||||||
|
import { configuredXss, md } from "@modrinth/utils";
|
||||||
import gradle from "highlight.js/lib/languages/gradle";
|
import gradle from "highlight.js/lib/languages/gradle";
|
||||||
import json from "highlight.js/lib/languages/json";
|
|
||||||
import ini from "highlight.js/lib/languages/ini";
|
import ini from "highlight.js/lib/languages/ini";
|
||||||
import yaml from "highlight.js/lib/languages/yaml";
|
import json from "highlight.js/lib/languages/json";
|
||||||
import xml from "highlight.js/lib/languages/xml";
|
|
||||||
import properties from "highlight.js/lib/languages/properties";
|
import properties from "highlight.js/lib/languages/properties";
|
||||||
import { md, configuredXss } from "@modrinth/utils";
|
import xml from "highlight.js/lib/languages/xml";
|
||||||
|
import yaml from "highlight.js/lib/languages/yaml";
|
||||||
|
|
||||||
/* REGISTRATION */
|
/* REGISTRATION */
|
||||||
// Scripting
|
// Scripting
|
||||||
@@ -54,7 +54,7 @@ export const renderHighlightedString = (string) =>
|
|||||||
if (lang && hljs.getLanguage(lang)) {
|
if (lang && hljs.getLanguage(lang)) {
|
||||||
try {
|
try {
|
||||||
return hljs.highlight(str, { language: lang }).value;
|
return hljs.highlight(str, { language: lang }).value;
|
||||||
} catch (__) {
|
} catch {
|
||||||
/* empty */
|
/* empty */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -231,6 +231,7 @@
|
|||||||
</template>
|
</template>
|
||||||
<template #revenue> <CurrencyIcon aria-hidden="true" /> Revenue </template>
|
<template #revenue> <CurrencyIcon aria-hidden="true" /> Revenue </template>
|
||||||
<template #analytics> <ChartIcon aria-hidden="true" /> Analytics </template>
|
<template #analytics> <ChartIcon aria-hidden="true" /> Analytics </template>
|
||||||
|
<template #moderation> <ModerationIcon aria-hidden="true" /> Moderation </template>
|
||||||
<template #sign-out> <LogOutIcon aria-hidden="true" /> Sign out </template>
|
<template #sign-out> <LogOutIcon aria-hidden="true" /> Sign out </template>
|
||||||
</OverflowMenu>
|
</OverflowMenu>
|
||||||
<ButtonStyled v-else color="brand">
|
<ButtonStyled v-else color="brand">
|
||||||
@@ -778,6 +779,7 @@ const userMenuOptions = computed(() => {
|
|||||||
link: "/settings",
|
link: "/settings",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
// TODO: Only show if user has projects
|
// TODO: Only show if user has projects
|
||||||
options = [
|
options = [
|
||||||
...options,
|
...options,
|
||||||
@@ -801,6 +803,24 @@ const userMenuOptions = computed(() => {
|
|||||||
link: "/dashboard/analytics",
|
link: "/dashboard/analytics",
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
if (
|
||||||
|
(auth.value && auth.value.user && auth.value.user.role === "moderator") ||
|
||||||
|
auth.value.user.role === "admin"
|
||||||
|
) {
|
||||||
|
options = [
|
||||||
|
...options,
|
||||||
|
{
|
||||||
|
divider: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "moderation",
|
||||||
|
color: "orange",
|
||||||
|
link: "/moderation/review",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
options = [
|
options = [
|
||||||
...options,
|
...options,
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1398,7 +1398,7 @@ try {
|
|||||||
|
|
||||||
versions = shallowRef(toRaw(versions));
|
versions = shallowRef(toRaw(versions));
|
||||||
featuredVersions = shallowRef(toRaw(featuredVersions));
|
featuredVersions = shallowRef(toRaw(featuredVersions));
|
||||||
} catch (error) {
|
} catch {
|
||||||
throw createError({
|
throw createError({
|
||||||
fatal: true,
|
fatal: true,
|
||||||
statusCode: 404,
|
statusCode: 404,
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ const props = defineProps<{
|
|||||||
members: User[];
|
members: User[];
|
||||||
currentMember: User;
|
currentMember: User;
|
||||||
dependencies: Dependency[];
|
dependencies: Dependency[];
|
||||||
resetProject: Function;
|
resetProject: (opts?: { dedupe?: "cancel" | "defer" }) => Promise<void>;
|
||||||
}>();
|
}>();
|
||||||
|
|
||||||
const version = computed(() => {
|
const version = computed(() => {
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ const windowsLink = ref(null);
|
|||||||
const linuxLinks = {
|
const linuxLinks = {
|
||||||
appImage: null,
|
appImage: null,
|
||||||
deb: null,
|
deb: null,
|
||||||
|
rpm: null,
|
||||||
thirdParty: "https://support.modrinth.com/en/articles/9298760",
|
thirdParty: "https://support.modrinth.com/en/articles/9298760",
|
||||||
};
|
};
|
||||||
const macLinks = {
|
const macLinks = {
|
||||||
@@ -57,6 +58,7 @@ macLinks.intel = launcherUpdates.value.platforms["darwin-x86_64"].install_urls[0
|
|||||||
windowsLink.value = launcherUpdates.value.platforms["windows-x86_64"].install_urls[0];
|
windowsLink.value = launcherUpdates.value.platforms["windows-x86_64"].install_urls[0];
|
||||||
linuxLinks.appImage = launcherUpdates.value.platforms["linux-x86_64"].install_urls[1];
|
linuxLinks.appImage = launcherUpdates.value.platforms["linux-x86_64"].install_urls[1];
|
||||||
linuxLinks.deb = launcherUpdates.value.platforms["linux-x86_64"].install_urls[0];
|
linuxLinks.deb = launcherUpdates.value.platforms["linux-x86_64"].install_urls[0];
|
||||||
|
linuxLinks.rpm = launcherUpdates.value.platforms["linux-x86_64"].install_urls[2];
|
||||||
|
|
||||||
onMounted(() => {
|
onMounted(() => {
|
||||||
os.value = navigator?.platform.toString();
|
os.value = navigator?.platform.toString();
|
||||||
@@ -879,7 +881,11 @@ useSeoMeta({
|
|||||||
</a>
|
</a>
|
||||||
<a :href="linuxLinks.deb" download="">
|
<a :href="linuxLinks.deb" download="">
|
||||||
<DownloadIcon />
|
<DownloadIcon />
|
||||||
<span> Download the Deb </span>
|
<span> Download the DEB </span>
|
||||||
|
</a>
|
||||||
|
<a :href="linuxLinks.rpm" download="">
|
||||||
|
<DownloadIcon />
|
||||||
|
<span> Download the RPM </span>
|
||||||
</a>
|
</a>
|
||||||
<a :href="linuxLinks.thirdParty" download="">
|
<a :href="linuxLinks.thirdParty" download="">
|
||||||
<LinkIcon />
|
<LinkIcon />
|
||||||
|
|||||||
@@ -195,7 +195,7 @@ const onAuthorize = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(formatMessage(messages.noRedirectUrlError));
|
throw new Error(formatMessage(messages.noRedirectUrlError));
|
||||||
} catch (error) {
|
} catch {
|
||||||
data.$notify({
|
data.$notify({
|
||||||
group: "main",
|
group: "main",
|
||||||
title: formatMessage(commonMessages.errorNotificationTitle),
|
title: formatMessage(commonMessages.errorNotificationTitle),
|
||||||
@@ -222,7 +222,7 @@ const onReject = async () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
throw new Error(formatMessage(messages.noRedirectUrlError));
|
throw new Error(formatMessage(messages.noRedirectUrlError));
|
||||||
} catch (error) {
|
} catch {
|
||||||
data.$notify({
|
data.$notify({
|
||||||
group: "main",
|
group: "main",
|
||||||
title: formatMessage(commonMessages.errorNotificationTitle),
|
title: formatMessage(commonMessages.errorNotificationTitle),
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ if (route.query.flow) {
|
|||||||
await useAuth(auth.value.token);
|
await useAuth(auth.value.token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
success.value = false;
|
success.value = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -612,7 +612,7 @@ const visibility = ref(collection.value.status);
|
|||||||
const removeProjects = ref([]);
|
const removeProjects = ref([]);
|
||||||
|
|
||||||
async function unfollowProject(project) {
|
async function unfollowProject(project) {
|
||||||
await userUnfollowProject(project);
|
await userFollowProject(project);
|
||||||
projects.value = projects.value.filter((x) => x.id !== project.id);
|
projects.value = projects.value.filter((x) => x.id !== project.id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -88,20 +88,6 @@
|
|||||||
></span
|
></span
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid-display__item">
|
|
||||||
<div class="label">Current balance</div>
|
|
||||||
<div class="value">
|
|
||||||
{{ $formatMoney(auth.user.payout_data.balance, true) }}
|
|
||||||
</div>
|
|
||||||
<NuxtLink
|
|
||||||
v-if="auth.user.payout_data.balance > 0"
|
|
||||||
class="goto-link"
|
|
||||||
to="/dashboard/revenue"
|
|
||||||
>
|
|
||||||
Withdraw earnings
|
|
||||||
<ChevronRightIcon class="featured-header-chevron" aria-hidden="true" />
|
|
||||||
</NuxtLink>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -2,21 +2,24 @@
|
|||||||
<div>
|
<div>
|
||||||
<section class="universal-card">
|
<section class="universal-card">
|
||||||
<h2 class="text-2xl">Revenue</h2>
|
<h2 class="text-2xl">Revenue</h2>
|
||||||
<div v-if="auth.user.payout_data.balance >= minWithdraw">
|
<div v-if="userBalance.available >= minWithdraw">
|
||||||
<p>
|
<p>
|
||||||
You have
|
You have
|
||||||
<strong>{{ $formatMoney(auth.user.payout_data.balance) }}</strong>
|
<strong>{{ $formatMoney(userBalance.available) }}</strong>
|
||||||
available to withdraw.
|
available to withdraw. <strong>{{ $formatMoney(userBalance.pending) }}</strong> of your
|
||||||
|
balance is <nuxt-link class="text-link" to="/legal/cmp-info#pending">pending</nuxt-link>.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<p v-else>
|
<p v-else>
|
||||||
You have made
|
You have made
|
||||||
<strong>{{ $formatMoney(auth.user.payout_data.balance) }}</strong
|
<strong>{{ $formatMoney(userBalance.available) }}</strong
|
||||||
>, which is under the minimum of ${{ minWithdraw }} to withdraw.
|
>, which is under the minimum of ${{ minWithdraw }} to withdraw.
|
||||||
|
<strong>{{ $formatMoney(userBalance.pending) }}</strong> of your balance is
|
||||||
|
<nuxt-link class="text-link" to="/legal/cmp-info#pending">pending</nuxt-link>.
|
||||||
</p>
|
</p>
|
||||||
<div class="input-group mt-4">
|
<div class="input-group mt-4">
|
||||||
<nuxt-link
|
<nuxt-link
|
||||||
v-if="auth.user.payout_data.balance >= minWithdraw"
|
v-if="userBalance.available >= minWithdraw"
|
||||||
class="iconified-button brand-button"
|
class="iconified-button brand-button"
|
||||||
to="/dashboard/revenue/withdraw"
|
to="/dashboard/revenue/withdraw"
|
||||||
>
|
>
|
||||||
@@ -81,6 +84,10 @@ import { TransferIcon, HistoryIcon, PayPalIcon, SaveIcon, XIcon } from "@modrint
|
|||||||
const auth = await useAuth();
|
const auth = await useAuth();
|
||||||
const minWithdraw = ref(0.01);
|
const minWithdraw = ref(0.01);
|
||||||
|
|
||||||
|
const { data: userBalance } = await useAsyncData(`payout/balance`, () =>
|
||||||
|
useBaseFetch(`payout/balance`, { apiVersion: 3 }),
|
||||||
|
);
|
||||||
|
|
||||||
async function updateVenmo() {
|
async function updateVenmo() {
|
||||||
startLoading();
|
startLoading();
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -88,7 +88,7 @@
|
|||||||
<p>
|
<p>
|
||||||
You are initiating a transfer of your revenue from Modrinth's Creator Monetization Program.
|
You are initiating a transfer of your revenue from Modrinth's Creator Monetization Program.
|
||||||
How much of your
|
How much of your
|
||||||
<strong>{{ $formatMoney(auth.user.payout_data.balance) }}</strong> balance would you like to
|
<strong>{{ $formatMoney(userBalance.available) }}</strong> balance would you like to transfer
|
||||||
transfer to {{ selectedMethod.name }}?
|
transfer to {{ selectedMethod.name }}?
|
||||||
</p>
|
</p>
|
||||||
<div class="confirmation-input">
|
<div class="confirmation-input">
|
||||||
@@ -212,10 +212,13 @@ const country = ref(
|
|||||||
countries.value.find((x) => x.id === (auth.value.user.payout_data.paypal_region ?? "US")),
|
countries.value.find((x) => x.id === (auth.value.user.payout_data.paypal_region ?? "US")),
|
||||||
);
|
);
|
||||||
|
|
||||||
const { data: payoutMethods, refresh: refreshPayoutMethods } = await useAsyncData(
|
const [{ data: userBalance }, { data: payoutMethods, refresh: refreshPayoutMethods }] =
|
||||||
`payout/methods?country=${country.value.id}`,
|
await Promise.all([
|
||||||
() => useBaseFetch(`payout/methods?country=${country.value.id}`, { apiVersion: 3 }),
|
useAsyncData(`payout/balance`, () => useBaseFetch(`payout/balance`, { apiVersion: 3 })),
|
||||||
);
|
useAsyncData(`payout/methods?country=${country.value.id}`, () =>
|
||||||
|
useBaseFetch(`payout/methods?country=${country.value.id}`, { apiVersion: 3 }),
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
|
||||||
const selectedMethodId = ref(payoutMethods.value[0].id);
|
const selectedMethodId = ref(payoutMethods.value[0].id);
|
||||||
const selectedMethod = computed(() =>
|
const selectedMethod = computed(() =>
|
||||||
@@ -295,10 +298,10 @@ const knownErrors = computed(() => {
|
|||||||
if (!parsedAmount.value && amount.value.length > 0) {
|
if (!parsedAmount.value && amount.value.length > 0) {
|
||||||
errors.push(`${amount.value} is not a valid amount`);
|
errors.push(`${amount.value} is not a valid amount`);
|
||||||
} else if (
|
} else if (
|
||||||
parsedAmount.value > auth.value.user.payout_data.balance ||
|
parsedAmount.value > userBalance.value.available ||
|
||||||
parsedAmount.value > maxWithdrawAmount.value
|
parsedAmount.value > maxWithdrawAmount.value
|
||||||
) {
|
) {
|
||||||
const maxAmount = Math.min(auth.value.user.payout_data.balance, maxWithdrawAmount.value);
|
const maxAmount = Math.min(userBalance.value.available, maxWithdrawAmount.value);
|
||||||
errors.push(`The amount must be no more than ${data.$formatMoney(maxAmount)}`);
|
errors.push(`The amount must be no more than ${data.$formatMoney(maxAmount)}`);
|
||||||
} else if (parsedAmount.value <= fees.value || parsedAmount.value < minWithdrawAmount.value) {
|
} else if (parsedAmount.value <= fees.value || parsedAmount.value < minWithdrawAmount.value) {
|
||||||
const minAmount = Math.max(fees.value + 0.01, minWithdrawAmount.value);
|
const minAmount = Math.max(fees.value + 0.01, minWithdrawAmount.value);
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="markdown-body">
|
<div class="markdown-body">
|
||||||
<h1>Rewards Program Information</h1>
|
<h1>Rewards Program Information</h1>
|
||||||
<p><em>Last modified: May 13, 2024</em></p>
|
<p><em>Last modified: Sep 12, 2024</em></p>
|
||||||
<p>
|
<p>
|
||||||
This page was created for transparency for how the rewards program works on Modrinth. Feel
|
This page was created for transparency for how the rewards program works on Modrinth. Feel
|
||||||
free to join our Discord or email
|
free to join our Discord or email
|
||||||
@@ -15,10 +15,11 @@
|
|||||||
<h2>Rewards Distribution</h2>
|
<h2>Rewards Distribution</h2>
|
||||||
<p>
|
<p>
|
||||||
We collect ad revenue on our website and app through our ad network
|
We collect ad revenue on our website and app through our ad network
|
||||||
<a href="https://adrinth.com">Adrinth</a>. We then distribute this ad revenue to creators.
|
<a href="https://adrinth.com">Adrinth</a>, which is powered by
|
||||||
|
<a href="https://aditude.io">Aditude</a>. We then distribute this ad revenue to creators.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
The advertising revenue of the entire website and app is split 90% to creators and 10% to
|
The advertising revenue of the entire website and app is split 75% to creators and 25% to
|
||||||
Modrinth.
|
Modrinth.
|
||||||
</p>
|
</p>
|
||||||
<p>
|
<p>
|
||||||
@@ -42,10 +43,10 @@
|
|||||||
</ul>
|
</ul>
|
||||||
<p>In this scenario, the earnings for each creator and Modrinth would be as follows:</p>
|
<p>In this scenario, the earnings for each creator and Modrinth would be as follows:</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Modrinth: $10 (10% of $100, the site's earnings for the day)</li>
|
<li>Modrinth: $25 (25% of $100, the site's earnings for the day)</li>
|
||||||
<li>User A: $58.69 ($90 * (10 + 30 + 100 + 10)/230)</li>
|
<li>User A: $48.91 ($75 * (10 + 30 + 100 + 10)/230)</li>
|
||||||
<li>User B: $12.52 (0.4 * $90 * (50 + 20 + 10 + 0)/230)</li>
|
<li>User B: $10.43 (0.4 * $75 * (50 + 20 + 10 + 0)/230)</li>
|
||||||
<li>User C: $18.78 (0.6 * $90 * (50 + 20 + 10 + 0)/230)</li>
|
<li>User C: $15.65 (0.6 * $75 * (50 + 20 + 10 + 0)/230)</li>
|
||||||
<li>Note: 230 is the sum of all page views and in-app downloads from above</li>
|
<li>Note: 230 is the sum of all page views and in-app downloads from above</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>
|
<p>
|
||||||
@@ -72,19 +73,62 @@
|
|||||||
</p>
|
</p>
|
||||||
<h3>What methods can I use withdraw money from my account? Are there any fees?</h3>
|
<h3>What methods can I use withdraw money from my account? Are there any fees?</h3>
|
||||||
<p>
|
<p>
|
||||||
Right now, you can use PayPal or Venmo to withdraw money from your Modrinth account. We are
|
Right now, you can use PayPal or Venmo to withdraw money from your Modrinth account. Gift card
|
||||||
working on more methods to withdraw money from your account. There are fees to withdraw money
|
withdrawal is also available. We are working on more methods to withdraw money from your
|
||||||
from your Modrinth account—see the revenue page in your dashboard for more information.
|
account. There are fees to withdraw money from your Modrinth account—see the revenue page in
|
||||||
|
your dashboard for more information.
|
||||||
</p>
|
</p>
|
||||||
<h3>Modrinth used to give 100% of project page revenue to creators. What changed?</h3>
|
<h3 id="pending">What does "pending" revenue mean in my dashboard?</h3>
|
||||||
<p>
|
<p>
|
||||||
While this is true, our new system (as of 08/05/23) gives more of the site's revenue to
|
Modrinth receives ad revenue from our ad providers on a NET 60 day basis. Due to this, not all
|
||||||
creators, so creators will earn more. In the old system, we would earn revenue through
|
revenue is immediately available to withdraw. We pay creators as soon as we receive the
|
||||||
advertisements in search and user profile pages. This amounted on average each month to about
|
money from our ad providers, which is 60 days after the last day of each month. This table
|
||||||
15-20% of the site's total advertising revenue (so a 80-85% split to creators). The new system
|
outlines some example dates of how NET 60 payments are made:
|
||||||
gives creators more revenue and a more favorable split towards creators (90%).
|
</p>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Date</th>
|
||||||
|
<th>Payment available date</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td>January 1st</td>
|
||||||
|
<td>March 31st</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>January 15th</td>
|
||||||
|
<td>March 31st</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>March 3rd</td>
|
||||||
|
<td>May 30th</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>June 30th</td>
|
||||||
|
<td>August 29th</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>July 14th</td>
|
||||||
|
<td>September 29th</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>October 12th</td>
|
||||||
|
<td>December 30th</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
<h3>How do I know Modrinth is being transparent about revenue?</h3>
|
||||||
|
<p>
|
||||||
|
We aim to be as transparent as possible with creator revenue. All of our code is open source,
|
||||||
|
including our
|
||||||
|
<a href="https://github.com/modrinth/labrinth/blob/master/src/queue/payouts.rs#L561">
|
||||||
|
revenue distribution system </a
|
||||||
|
>. We also have an
|
||||||
|
<a href="https://api.modrinth.com/v3/payout/platform_revenue">API route</a> that allows users
|
||||||
|
to query exact daily revenue for the site.
|
||||||
</p>
|
</p>
|
||||||
<h3></h3>
|
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|||||||
@@ -371,6 +371,22 @@
|
|||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<section id="data-export" class="universal-card">
|
||||||
|
<h2>Data export</h2>
|
||||||
|
<p>
|
||||||
|
Request a copy of all your personal data you have uploaded to Modrinth. This may take
|
||||||
|
several minutes to complete.
|
||||||
|
</p>
|
||||||
|
<a v-if="generated" class="iconified-button" :href="generated" download="export.json">
|
||||||
|
<DownloadIcon />
|
||||||
|
Download export
|
||||||
|
</a>
|
||||||
|
<button v-else class="iconified-button" :disabled="generatingExport" @click="exportData">
|
||||||
|
<template v-if="generatingExport"> <UpdatedIcon /> Generating export... </template>
|
||||||
|
<template v-else> <UpdatedIcon /> Generate export </template>
|
||||||
|
</button>
|
||||||
|
</section>
|
||||||
|
|
||||||
<section id="delete-account" class="universal-card">
|
<section id="delete-account" class="universal-card">
|
||||||
<h2>Delete account</h2>
|
<h2>Delete account</h2>
|
||||||
<p>
|
<p>
|
||||||
@@ -391,16 +407,18 @@
|
|||||||
|
|
||||||
<script setup>
|
<script setup>
|
||||||
import {
|
import {
|
||||||
EditIcon,
|
|
||||||
SaveIcon,
|
|
||||||
TrashIcon,
|
|
||||||
PlusIcon,
|
|
||||||
SettingsIcon,
|
|
||||||
XIcon,
|
|
||||||
LeftArrowIcon,
|
|
||||||
RightArrowIcon,
|
|
||||||
CheckIcon,
|
CheckIcon,
|
||||||
|
EditIcon,
|
||||||
ExternalIcon,
|
ExternalIcon,
|
||||||
|
LeftArrowIcon,
|
||||||
|
PlusIcon,
|
||||||
|
RightArrowIcon,
|
||||||
|
SaveIcon,
|
||||||
|
SettingsIcon,
|
||||||
|
TrashIcon,
|
||||||
|
UpdatedIcon,
|
||||||
|
XIcon,
|
||||||
|
DownloadIcon,
|
||||||
} from "@modrinth/assets";
|
} from "@modrinth/assets";
|
||||||
import QrcodeVue from "qrcode.vue";
|
import QrcodeVue from "qrcode.vue";
|
||||||
import GitHubIcon from "assets/icons/auth/sso-github.svg";
|
import GitHubIcon from "assets/icons/auth/sso-github.svg";
|
||||||
@@ -538,7 +556,7 @@ async function verifyTwoFactorCode() {
|
|||||||
backupCodes.value = res.backup_codes;
|
backupCodes.value = res.backup_codes;
|
||||||
twoFactorStep.value = 2;
|
twoFactorStep.value = 2;
|
||||||
await useAuth(auth.value.token);
|
await useAuth(auth.value.token);
|
||||||
} catch (err) {
|
} catch {
|
||||||
twoFactorIncorrect.value = true;
|
twoFactorIncorrect.value = true;
|
||||||
}
|
}
|
||||||
stopLoading();
|
stopLoading();
|
||||||
@@ -555,7 +573,7 @@ async function removeTwoFactor() {
|
|||||||
});
|
});
|
||||||
manageTwoFactorModal.value.hide();
|
manageTwoFactorModal.value.hide();
|
||||||
await useAuth(auth.value.token);
|
await useAuth(auth.value.token);
|
||||||
} catch (err) {
|
} catch {
|
||||||
twoFactorIncorrect.value = true;
|
twoFactorIncorrect.value = true;
|
||||||
}
|
}
|
||||||
stopLoading();
|
stopLoading();
|
||||||
@@ -614,6 +632,34 @@ async function deleteAccount() {
|
|||||||
|
|
||||||
stopLoading();
|
stopLoading();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const generatingExport = ref(false);
|
||||||
|
const generated = ref();
|
||||||
|
async function exportData() {
|
||||||
|
startLoading();
|
||||||
|
generatingExport.value = true;
|
||||||
|
try {
|
||||||
|
const res = await useBaseFetch("gdpr/export", {
|
||||||
|
method: "POST",
|
||||||
|
internal: true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const jsonString = JSON.stringify(res, null, 2);
|
||||||
|
|
||||||
|
const blob = new Blob([jsonString], { type: "application/json" });
|
||||||
|
generated.value = URL.createObjectURL(blob);
|
||||||
|
} catch (err) {
|
||||||
|
data.$notify({
|
||||||
|
group: "main",
|
||||||
|
title: "An error occurred",
|
||||||
|
text: err.data.description,
|
||||||
|
type: "error",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
generatingExport.value = false;
|
||||||
|
stopLoading();
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
canvas {
|
canvas {
|
||||||
|
|||||||
@@ -301,7 +301,7 @@ const canSubmit = computed(() => {
|
|||||||
const url = new URL(uri);
|
const url = new URL(uri);
|
||||||
return !!url;
|
return !!url;
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch {
|
||||||
allValid = false;
|
allValid = false;
|
||||||
}
|
}
|
||||||
return filledIn && (oneValid || allValid);
|
return filledIn && (oneValid || allValid);
|
||||||
|
|||||||
@@ -17,33 +17,24 @@
|
|||||||
<span class="font-bold text-primary">
|
<span class="font-bold text-primary">
|
||||||
<template v-if="charge.product.metadata.type === 'midas'"> Modrinth Plus </template>
|
<template v-if="charge.product.metadata.type === 'midas'"> Modrinth Plus </template>
|
||||||
<template v-else> Unknown product </template>
|
<template v-else> Unknown product </template>
|
||||||
<template v-if="charge.metadata.modrinth_subscription_interval">
|
<template v-if="charge.subscription_interval">
|
||||||
{{ charge.metadata.modrinth_subscription_interval }}
|
{{ charge.subscription_interval }}
|
||||||
</template>
|
</template>
|
||||||
</span>
|
</span>
|
||||||
⋅
|
⋅
|
||||||
<span>{{ formatPrice(charge.amount, charge.currency) }}</span>
|
<span>{{ formatPrice(charge.amount, charge.currency_code) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<Badge :color="charge.status === 'succeeded' ? 'green' : 'red'" :type="charge.status" />
|
<Badge :color="charge.status === 'succeeded' ? 'green' : 'red'" :type="charge.status" />
|
||||||
⋅
|
⋅
|
||||||
{{ $dayjs.unix(charge.created).format("YYYY-MM-DD") }}
|
{{ $dayjs(charge.due).format("YYYY-MM-DD") }}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<a
|
|
||||||
v-if="charge.receipt_url"
|
|
||||||
class="iconified-button raised-button"
|
|
||||||
:href="charge.receipt_url"
|
|
||||||
>
|
|
||||||
<ReceiptTextIcon />
|
|
||||||
View receipt
|
|
||||||
</a>
|
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ReceiptTextIcon } from "@modrinth/assets";
|
|
||||||
import { Breadcrumbs, Badge } from "@modrinth/ui";
|
import { Breadcrumbs, Badge } from "@modrinth/ui";
|
||||||
import { products } from "~/generated/state.json";
|
import { products } from "~/generated/state.json";
|
||||||
|
|
||||||
@@ -58,15 +49,17 @@ const { data: charges } = await useAsyncData(
|
|||||||
() => useBaseFetch("billing/payments", { internal: true }),
|
() => useBaseFetch("billing/payments", { internal: true }),
|
||||||
{
|
{
|
||||||
transform: (charges) => {
|
transform: (charges) => {
|
||||||
return charges.map((charge) => {
|
return charges
|
||||||
const product = products.find((product) =>
|
.filter((charge) => charge.status !== "open" && charge.status !== "cancelled")
|
||||||
product.prices.some((price) => price.id === charge.metadata.modrinth_price_id),
|
.map((charge) => {
|
||||||
);
|
const product = products.find((product) =>
|
||||||
|
product.prices.some((price) => price.id === charge.price_id),
|
||||||
|
);
|
||||||
|
|
||||||
charge.product = product;
|
charge.product = product;
|
||||||
|
|
||||||
return charge;
|
return charge;
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -8,22 +8,20 @@
|
|||||||
:title="formatMessage(cancelModalMessages.title)"
|
:title="formatMessage(cancelModalMessages.title)"
|
||||||
:description="formatMessage(cancelModalMessages.description)"
|
:description="formatMessage(cancelModalMessages.description)"
|
||||||
:proceed-label="formatMessage(cancelModalMessages.action)"
|
:proceed-label="formatMessage(cancelModalMessages.action)"
|
||||||
@proceed="cancelSubscription(cancelSubscriptionId)"
|
@proceed="cancelSubscription(cancelSubscriptionId, true)"
|
||||||
/>
|
/>
|
||||||
<div class="flex flex-wrap justify-between gap-4">
|
<div class="flex flex-wrap justify-between gap-4">
|
||||||
<div class="flex flex-col gap-4">
|
<div class="flex flex-col gap-4">
|
||||||
<template v-if="midasSubscription">
|
<template v-if="midasCharge">
|
||||||
<span v-if="midasSubscription.status === 'active'">
|
<span v-if="midasCharge.status === 'open'"> You're currently subscribed to: </span>
|
||||||
You're currently subscribed to:
|
<span v-else-if="midasCharge.status === 'processing'" class="text-orange">
|
||||||
</span>
|
|
||||||
<span v-else-if="midasSubscription.status === 'payment-processing'" class="text-orange">
|
|
||||||
Your payment is being processed. Perks will activate once payment is complete.
|
Your payment is being processed. Perks will activate once payment is complete.
|
||||||
</span>
|
</span>
|
||||||
<span v-else-if="midasSubscription.status === 'cancelled'">
|
<span v-else-if="midasCharge.status === 'cancelled'">
|
||||||
You've cancelled your subscription. <br />
|
You've cancelled your subscription. <br />
|
||||||
You will retain your perks until the end of the current billing cycle.
|
You will retain your perks until the end of the current billing cycle.
|
||||||
</span>
|
</span>
|
||||||
<span v-else-if="midasSubscription.status === 'payment-failed'" class="text-red">
|
<span v-else-if="midasCharge.status === 'failed'" class="text-red">
|
||||||
Your subscription payment failed. Please update your payment method.
|
Your subscription payment failed. Please update your payment method.
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
@@ -49,34 +47,31 @@
|
|||||||
<div class="flex w-full flex-wrap justify-between gap-4 xl:w-auto xl:flex-col">
|
<div class="flex w-full flex-wrap justify-between gap-4 xl:w-auto xl:flex-col">
|
||||||
<div class="flex flex-col gap-1 xl:ml-auto xl:text-right">
|
<div class="flex flex-col gap-1 xl:ml-auto xl:text-right">
|
||||||
<span class="text-2xl font-bold text-dark">
|
<span class="text-2xl font-bold text-dark">
|
||||||
<template v-if="midasSubscription">
|
<template v-if="midasCharge">
|
||||||
{{
|
{{
|
||||||
formatPrice(
|
formatPrice(
|
||||||
vintl.locale,
|
vintl.locale,
|
||||||
midasSubscriptionPrice.prices.intervals[midasSubscription.interval],
|
midasSubscriptionPrice.prices.intervals[midasCharge.subscription_interval],
|
||||||
midasSubscriptionPrice.currency_code,
|
midasSubscriptionPrice.currency_code,
|
||||||
)
|
)
|
||||||
}}
|
}}
|
||||||
/
|
/
|
||||||
{{ midasSubscription.interval }}
|
{{ midasCharge.subscription_interval }}
|
||||||
</template>
|
</template>
|
||||||
<template v-else>
|
<template v-else>
|
||||||
{{ formatPrice(vintl.locale, price.prices.intervals.monthly, price.currency_code) }}
|
{{ formatPrice(vintl.locale, price.prices.intervals.monthly, price.currency_code) }}
|
||||||
/ month
|
/ month
|
||||||
</template>
|
</template>
|
||||||
</span>
|
</span>
|
||||||
<template v-if="midasSubscription">
|
<template v-if="midasCharge">
|
||||||
<span class="text-sm text-secondary">
|
<span class="text-sm text-secondary">
|
||||||
Since {{ $dayjs(midasSubscription.created).format("MMMM D, YYYY") }}
|
Since {{ $dayjs(midasSubscription.created).format("MMMM D, YYYY") }}
|
||||||
</span>
|
</span>
|
||||||
<span v-if="midasSubscription.status === 'active'" class="text-sm text-secondary">
|
<span v-if="midasCharge.status === 'open'" class="text-sm text-secondary">
|
||||||
Renews {{ $dayjs(midasSubscription.expires).format("MMMM D, YYYY") }}
|
Renews {{ $dayjs(midasCharge.due).format("MMMM D, YYYY") }}
|
||||||
</span>
|
</span>
|
||||||
<span
|
<span v-else-if="midasCharge.status === 'cancelled'" class="text-sm text-secondary">
|
||||||
v-else-if="midasSubscription.status === 'cancelled'"
|
Expires {{ $dayjs(midasCharge.due).format("MMMM D, YYYY") }}
|
||||||
class="text-sm text-secondary"
|
|
||||||
>
|
|
||||||
Expires {{ $dayjs(midasSubscription.expires).format("MMMM D, YYYY") }}
|
|
||||||
</span>
|
</span>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@@ -90,11 +85,11 @@
|
|||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
v-if="midasSubscription && midasSubscription.status === 'payment-failed'"
|
v-if="midasCharge && midasCharge.status === 'failed'"
|
||||||
class="ml-auto flex flex-row-reverse items-center gap-2"
|
class="ml-auto flex flex-row-reverse items-center gap-2"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
v-if="midasSubscription && midasSubscription.status === 'payment-failed'"
|
v-if="midasCharge && midasCharge.status === 'failed'"
|
||||||
class="iconified-button raised-button"
|
class="iconified-button raised-button"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
@@ -123,7 +118,7 @@
|
|||||||
</OverflowMenu>
|
</OverflowMenu>
|
||||||
</div>
|
</div>
|
||||||
<button
|
<button
|
||||||
v-else-if="midasSubscription && midasSubscription.status !== 'cancelled'"
|
v-else-if="midasCharge && midasCharge.status !== 'cancelled'"
|
||||||
class="iconified-button raised-button !ml-auto"
|
class="iconified-button raised-button !ml-auto"
|
||||||
@click="
|
@click="
|
||||||
() => {
|
() => {
|
||||||
@@ -134,6 +129,13 @@
|
|||||||
>
|
>
|
||||||
<XIcon /> Cancel
|
<XIcon /> Cancel
|
||||||
</button>
|
</button>
|
||||||
|
<button
|
||||||
|
v-else-if="midasCharge && midasCharge.status === 'cancelled'"
|
||||||
|
class="btn btn-purple btn-large ml-auto"
|
||||||
|
@click="cancelSubscription(midasSubscription.id, false)"
|
||||||
|
>
|
||||||
|
<RightArrowIcon /> Resubscribe
|
||||||
|
</button>
|
||||||
<button
|
<button
|
||||||
v-else
|
v-else
|
||||||
class="btn btn-purple btn-large ml-auto"
|
class="btn btn-purple btn-large ml-auto"
|
||||||
@@ -474,12 +476,14 @@ function loadStripe() {
|
|||||||
|
|
||||||
const [
|
const [
|
||||||
{ data: paymentMethods, refresh: refreshPaymentMethods },
|
{ data: paymentMethods, refresh: refreshPaymentMethods },
|
||||||
|
{ data: charges, refresh: refreshCharges },
|
||||||
{ data: customer, refresh: refreshCustomer },
|
{ data: customer, refresh: refreshCustomer },
|
||||||
{ data: subscriptions, refresh: refreshSubscriptions },
|
{ data: subscriptions, refresh: refreshSubscriptions },
|
||||||
] = await Promise.all([
|
] = await Promise.all([
|
||||||
useAsyncData("billing/payment_methods", () =>
|
useAsyncData("billing/payment_methods", () =>
|
||||||
useBaseFetch("billing/payment_methods", { internal: true }),
|
useBaseFetch("billing/payment_methods", { internal: true }),
|
||||||
),
|
),
|
||||||
|
useAsyncData("billing/payments", () => useBaseFetch("billing/payments", { internal: true })),
|
||||||
useAsyncData("billing/customer", () => useBaseFetch("billing/customer", { internal: true })),
|
useAsyncData("billing/customer", () => useBaseFetch("billing/customer", { internal: true })),
|
||||||
useAsyncData("billing/subscriptions", () =>
|
useAsyncData("billing/subscriptions", () =>
|
||||||
useBaseFetch("billing/subscriptions", { internal: true }),
|
useBaseFetch("billing/subscriptions", { internal: true }),
|
||||||
@@ -487,18 +491,30 @@ const [
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
async function refresh() {
|
async function refresh() {
|
||||||
await Promise.all([refreshPaymentMethods(), refreshCustomer(), refreshSubscriptions()]);
|
await Promise.all([
|
||||||
|
refreshPaymentMethods(),
|
||||||
|
refreshCharges(),
|
||||||
|
refreshCustomer(),
|
||||||
|
refreshSubscriptions(),
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const midasProduct = ref(products.find((x) => x.metadata.type === "midas"));
|
const midasProduct = ref(products.find((x) => x.metadata.type === "midas"));
|
||||||
const midasSubscription = computed(() =>
|
const midasSubscription = computed(() =>
|
||||||
subscriptions.value.find((x) => midasProduct.value.prices.find((y) => y.id === x.price_id)),
|
subscriptions.value.find(
|
||||||
|
(x) => x.status === "provisioned" && midasProduct.value.prices.find((y) => y.id === x.price_id),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
const midasSubscriptionPrice = computed(() =>
|
const midasSubscriptionPrice = computed(() =>
|
||||||
midasSubscription.value
|
midasSubscription.value
|
||||||
? midasProduct.value.prices.find((x) => x.id === midasSubscription.value.price_id)
|
? midasProduct.value.prices.find((x) => x.id === midasSubscription.value.price_id)
|
||||||
: null,
|
: null,
|
||||||
);
|
);
|
||||||
|
const midasCharge = computed(() =>
|
||||||
|
midasSubscription.value
|
||||||
|
? charges.value.find((x) => x.subscription_id === midasSubscription.value.id)
|
||||||
|
: null,
|
||||||
|
);
|
||||||
|
|
||||||
const purchaseModal = ref();
|
const purchaseModal = ref();
|
||||||
const country = useUserCountry();
|
const country = useUserCountry();
|
||||||
@@ -524,10 +540,18 @@ if (route.query.priceId && route.query.plan && route.query.redirect_status) {
|
|||||||
price_id: route.query.priceId,
|
price_id: route.query.priceId,
|
||||||
interval: route.query.plan,
|
interval: route.query.plan,
|
||||||
created: Date.now(),
|
created: Date.now(),
|
||||||
expires: route.query.plan === "yearly" ? Date.now() + 31536000000 : Date.now() + 2629746000,
|
|
||||||
status,
|
status,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
charges.value.push({
|
||||||
|
id: "temp",
|
||||||
|
price_id: route.query.priceId,
|
||||||
|
subscription_id: "temp",
|
||||||
|
status: "open",
|
||||||
|
due: Date.now() + (route.query.plan === "yearly" ? 31536000000 : 2629746000),
|
||||||
|
subscription_interval: route.query.plan,
|
||||||
|
});
|
||||||
|
|
||||||
await router.replace({ query: {} });
|
await router.replace({ query: {} });
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -655,12 +679,15 @@ async function removePaymentMethod(index) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const cancelSubscriptionId = ref();
|
const cancelSubscriptionId = ref();
|
||||||
async function cancelSubscription(id) {
|
async function cancelSubscription(id, cancelled) {
|
||||||
startLoading();
|
startLoading();
|
||||||
try {
|
try {
|
||||||
await useBaseFetch(`billing/subscription/${id}`, {
|
await useBaseFetch(`billing/subscription/${id}`, {
|
||||||
internal: true,
|
internal: true,
|
||||||
method: "DELETE",
|
method: "PATCH",
|
||||||
|
body: {
|
||||||
|
cancelled,
|
||||||
|
},
|
||||||
});
|
});
|
||||||
await refresh();
|
await refresh();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ async function changeLocale(value: string) {
|
|||||||
try {
|
try {
|
||||||
await vintl.changeLocale(value);
|
await vintl.changeLocale(value);
|
||||||
$failedLocale.value = undefined;
|
$failedLocale.value = undefined;
|
||||||
} catch (err) {
|
} catch {
|
||||||
$failedLocale.value = value;
|
$failedLocale.value = value;
|
||||||
} finally {
|
} finally {
|
||||||
$changingTo.value = undefined;
|
$changingTo.value = undefined;
|
||||||
|
|||||||
@@ -1,90 +1,134 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<title>Modrinth App Ad</title>
|
<title>Modrinth App Ad</title>
|
||||||
<script
|
<script
|
||||||
src="https://dn0qt3r0xannq.cloudfront.net/modrinth-7JfmkEIXEp/modrinth-longform/prebid-load.js"
|
src="https://dn0qt3r0xannq.cloudfront.net/modrinth-7JfmkEIXEp/modrinth-longform/prebid-load.js"
|
||||||
async
|
async
|
||||||
></script>
|
></script>
|
||||||
<link rel="preload" href="https://www.googletagservices.com/tag/js/gpt.js" as="script" />
|
<link rel="preload" href="https://www.googletagservices.com/tag/js/gpt.js" as="script" />
|
||||||
<style>
|
<style>
|
||||||
* {
|
* {
|
||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
|
||||||
|
|
||||||
.ads-container {
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
overflow: hidden;
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
|
|
||||||
#plus-link {
|
|
||||||
width: 100vw;
|
|
||||||
height: 100vh;
|
|
||||||
position: absolute;
|
|
||||||
top: 0;
|
|
||||||
left: 0;
|
|
||||||
z-index: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#modrinth-rail-1 {
|
|
||||||
border-radius: 1rem;
|
|
||||||
position: absolute;
|
|
||||||
left: 0;
|
|
||||||
bottom: 0;
|
|
||||||
z-index: 2;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="ads-container">
|
|
||||||
<a id="plus-link" href="https://modrinth.com/plus" target="_blank"></a>
|
|
||||||
<div id="modrinth-rail-1" />
|
|
||||||
</div>
|
|
||||||
<script>
|
|
||||||
window.tude = window.tude || { cmd: [] };
|
|
||||||
tude.cmd.push(function () {
|
|
||||||
tude.refreshAdsViaDivMappings([
|
|
||||||
{
|
|
||||||
divId: "modrinth-rail-1",
|
|
||||||
baseDivId: "pb-slot-square-2",
|
|
||||||
},
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
|
|
||||||
let lastUrl = null
|
|
||||||
window.addEventListener(
|
|
||||||
"message",
|
|
||||||
(event) => {
|
|
||||||
if (event.data.modrinthOpenUrl && window.__TAURI_INTERNALS__ && lastUrl !== event.data.modrinthOpenUrl) {
|
|
||||||
lastUrl = event.data.modrinthOpenUrl
|
|
||||||
// window.__TAURI_INTERNALS__.invoke("plugin:shell|open", {
|
|
||||||
// path: event.data.modrinthOpenUrl,
|
|
||||||
// });
|
|
||||||
|
|
||||||
setTimeout(() => {
|
|
||||||
lastUrl = null
|
|
||||||
}, 500)
|
|
||||||
}
|
}
|
||||||
},
|
|
||||||
false,
|
|
||||||
);
|
|
||||||
|
|
||||||
window.addEventListener("mousewheel", (event) => {
|
.ads-container {
|
||||||
if (window.__TAURI_INTERNALS__) {
|
width: 100vw;
|
||||||
window.__TAURI_INTERNALS__.invoke("plugin:ads|scroll_ads_window", {
|
height: 100vh;
|
||||||
scroll: event.deltaY,
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
|
||||||
|
#plus-link {
|
||||||
|
width: 100vw;
|
||||||
|
height: 100vh;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
z-index: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#modrinth-rail-1 {
|
||||||
|
border-radius: 1rem;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
top: 0;
|
||||||
|
z-index: 2;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="ads-container">
|
||||||
|
<div id="plus-link"></div>
|
||||||
|
<div id="modrinth-rail-1"></div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
function getCookie(name) {
|
||||||
|
function escape(s) {
|
||||||
|
return s.replace(/([.*+?\^$(){}|\[\]\/\\])/g, "\\$1");
|
||||||
|
}
|
||||||
|
|
||||||
|
const match = document.cookie.match(RegExp("(?:^|;\\s*)" + escape(name) + "=([^;]*)"));
|
||||||
|
return match ? match[1] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
function initAds(personalized) {
|
||||||
|
window.tude = window.tude || { cmd: [] };
|
||||||
|
|
||||||
|
tude.cmd.push(function () {
|
||||||
|
tude.refreshAdsViaDivMappings([
|
||||||
|
{
|
||||||
|
divId: "modrinth-rail-1",
|
||||||
|
baseDivId: "pb-slot-square-2",
|
||||||
|
},
|
||||||
|
]);
|
||||||
|
|
||||||
|
tude.setPrivacySettings({
|
||||||
|
personalizedAds: personalized ?? true,
|
||||||
|
});
|
||||||
|
|
||||||
|
const hash = getCookie("modrinth-app-token");
|
||||||
|
console.log(hash);
|
||||||
|
tude.setIdProfile({
|
||||||
|
e: hash,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
if (window.__TAURI_INTERNALS__) {
|
||||||
|
window.__TAURI_INTERNALS__
|
||||||
|
.invoke("plugin:ads|get_ads_personalization", {})
|
||||||
|
.then(initAds)
|
||||||
|
.catch(() => initAds(true));
|
||||||
|
} else {
|
||||||
|
initAds(true);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
initAds(true);
|
||||||
|
console.error(err);
|
||||||
|
}
|
||||||
|
|
||||||
|
window.addEventListener(
|
||||||
|
"message",
|
||||||
|
(event) => {
|
||||||
|
if (event.data.modrinthAdClick && window.__TAURI_INTERNALS__) {
|
||||||
|
window.__TAURI_INTERNALS__.invoke("plugin:ads|record_ads_click", {});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.data.modrinthOpenUrl && window.__TAURI_INTERNALS__) {
|
||||||
|
window.__TAURI_INTERNALS__.invoke("plugin:ads|open_link", {
|
||||||
|
path: event.data.modrinthOpenUrl,
|
||||||
|
origin: event.origin,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
window.addEventListener("mousewheel", (event) => {
|
||||||
|
if (window.__TAURI_INTERNALS__) {
|
||||||
|
window.__TAURI_INTERNALS__.invoke("plugin:ads|scroll_ads_window", {
|
||||||
|
scroll: event.deltaY,
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
document.addEventListener("contextmenu", (event) => event.preventDefault());
|
document.addEventListener("contextmenu", (event) => event.preventDefault());
|
||||||
</script>
|
|
||||||
</body>
|
const plusLink = document.getElementById("plus-link");
|
||||||
|
plusLink.addEventListener("click", function () {
|
||||||
|
window.__TAURI_INTERNALS__.invoke("plugin:ads|record_ads_click", {});
|
||||||
|
window.__TAURI_INTERNALS__.invoke("plugin:ads|open_link", {
|
||||||
|
path: "https://modrinth.com/plus",
|
||||||
|
origin: "https://modrinth.com",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
12
packages/app-lib/.sqlx/query-26e3ed8680f6c492b03b458aabfb3f94fddc753b343ef705263188945d0e578d.json
generated
Normal file
12
packages/app-lib/.sqlx/query-26e3ed8680f6c492b03b458aabfb3f94fddc753b343ef705263188945d0e578d.json
generated
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"db_name": "SQLite",
|
||||||
|
"query": "\n UPDATE settings\n SET\n max_concurrent_writes = $1,\n max_concurrent_downloads = $2,\n\n theme = $3,\n default_page = $4,\n collapsed_navigation = $5,\n advanced_rendering = $6,\n native_decorations = $7,\n\n discord_rpc = $8,\n developer_mode = $9,\n telemetry = $10,\n personalized_ads = $11,\n\n onboarded = $12,\n\n extra_launch_args = jsonb($13),\n custom_env_vars = jsonb($14),\n mc_memory_max = $15,\n mc_force_fullscreen = $16,\n mc_game_resolution_x = $17,\n mc_game_resolution_y = $18,\n hide_on_process_start = $19,\n\n hook_pre_launch = $20,\n hook_wrapper = $21,\n hook_post_exit = $22,\n\n custom_dir = $23,\n prev_custom_dir = $24,\n migrated = $25\n ",
|
||||||
|
"describe": {
|
||||||
|
"columns": [],
|
||||||
|
"parameters": {
|
||||||
|
"Right": 25
|
||||||
|
},
|
||||||
|
"nullable": []
|
||||||
|
},
|
||||||
|
"hash": "26e3ed8680f6c492b03b458aabfb3f94fddc753b343ef705263188945d0e578d"
|
||||||
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"db_name": "SQLite",
|
"db_name": "SQLite",
|
||||||
"query": "\n SELECT\n max_concurrent_writes, max_concurrent_downloads,\n theme, default_page, collapsed_navigation, advanced_rendering, native_decorations,\n discord_rpc, developer_mode, telemetry,\n onboarded,\n json(extra_launch_args) extra_launch_args, json(custom_env_vars) custom_env_vars,\n mc_memory_max, mc_force_fullscreen, mc_game_resolution_x, mc_game_resolution_y, hide_on_process_start,\n hook_pre_launch, hook_wrapper, hook_post_exit,\n custom_dir, prev_custom_dir, migrated\n FROM settings\n ",
|
"query": "\n SELECT\n max_concurrent_writes, max_concurrent_downloads,\n theme, default_page, collapsed_navigation, advanced_rendering, native_decorations,\n discord_rpc, developer_mode, telemetry, personalized_ads,\n onboarded,\n json(extra_launch_args) extra_launch_args, json(custom_env_vars) custom_env_vars,\n mc_memory_max, mc_force_fullscreen, mc_game_resolution_x, mc_game_resolution_y, hide_on_process_start,\n hook_pre_launch, hook_wrapper, hook_post_exit,\n custom_dir, prev_custom_dir, migrated\n FROM settings\n ",
|
||||||
"describe": {
|
"describe": {
|
||||||
"columns": [
|
"columns": [
|
||||||
{
|
{
|
||||||
@@ -54,73 +54,78 @@
|
|||||||
"type_info": "Integer"
|
"type_info": "Integer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "onboarded",
|
"name": "personalized_ads",
|
||||||
"ordinal": 10,
|
"ordinal": 10,
|
||||||
"type_info": "Integer"
|
"type_info": "Integer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "extra_launch_args",
|
"name": "onboarded",
|
||||||
"ordinal": 11,
|
"ordinal": 11,
|
||||||
"type_info": "Text"
|
"type_info": "Integer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "custom_env_vars",
|
"name": "extra_launch_args",
|
||||||
"ordinal": 12,
|
"ordinal": 12,
|
||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mc_memory_max",
|
"name": "custom_env_vars",
|
||||||
"ordinal": 13,
|
"ordinal": 13,
|
||||||
"type_info": "Integer"
|
"type_info": "Text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mc_force_fullscreen",
|
"name": "mc_memory_max",
|
||||||
"ordinal": 14,
|
"ordinal": 14,
|
||||||
"type_info": "Integer"
|
"type_info": "Integer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mc_game_resolution_x",
|
"name": "mc_force_fullscreen",
|
||||||
"ordinal": 15,
|
"ordinal": 15,
|
||||||
"type_info": "Integer"
|
"type_info": "Integer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "mc_game_resolution_y",
|
"name": "mc_game_resolution_x",
|
||||||
"ordinal": 16,
|
"ordinal": 16,
|
||||||
"type_info": "Integer"
|
"type_info": "Integer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "hide_on_process_start",
|
"name": "mc_game_resolution_y",
|
||||||
"ordinal": 17,
|
"ordinal": 17,
|
||||||
"type_info": "Integer"
|
"type_info": "Integer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "hook_pre_launch",
|
"name": "hide_on_process_start",
|
||||||
"ordinal": 18,
|
"ordinal": 18,
|
||||||
"type_info": "Text"
|
"type_info": "Integer"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "hook_wrapper",
|
"name": "hook_pre_launch",
|
||||||
"ordinal": 19,
|
"ordinal": 19,
|
||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "hook_post_exit",
|
"name": "hook_wrapper",
|
||||||
"ordinal": 20,
|
"ordinal": 20,
|
||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "custom_dir",
|
"name": "hook_post_exit",
|
||||||
"ordinal": 21,
|
"ordinal": 21,
|
||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "prev_custom_dir",
|
"name": "custom_dir",
|
||||||
"ordinal": 22,
|
"ordinal": 22,
|
||||||
"type_info": "Text"
|
"type_info": "Text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "migrated",
|
"name": "prev_custom_dir",
|
||||||
"ordinal": 23,
|
"ordinal": 23,
|
||||||
|
"type_info": "Text"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "migrated",
|
||||||
|
"ordinal": 24,
|
||||||
"type_info": "Integer"
|
"type_info": "Integer"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -139,6 +144,7 @@
|
|||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
false,
|
false,
|
||||||
|
false,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
false,
|
false,
|
||||||
@@ -154,5 +160,5 @@
|
|||||||
false
|
false
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
"hash": "03d1aeddf7788320530c447a82342aecdb4099ce183dd9106c4bcc47604cb080"
|
"hash": "8e19c9cdb0aaa48509724e82f6e8f212c9cd2112fdba77cfeee206025af47761"
|
||||||
}
|
}
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
{
|
|
||||||
"db_name": "SQLite",
|
|
||||||
"query": "\n UPDATE settings\n SET\n max_concurrent_writes = $1,\n max_concurrent_downloads = $2,\n\n theme = $3,\n default_page = $4,\n collapsed_navigation = $5,\n advanced_rendering = $6,\n native_decorations = $7,\n\n discord_rpc = $8,\n developer_mode = $9,\n telemetry = $10,\n\n onboarded = $11,\n\n extra_launch_args = jsonb($12),\n custom_env_vars = jsonb($13),\n mc_memory_max = $14,\n mc_force_fullscreen = $15,\n mc_game_resolution_x = $16,\n mc_game_resolution_y = $17,\n hide_on_process_start = $18,\n\n hook_pre_launch = $19,\n hook_wrapper = $20,\n hook_post_exit = $21,\n\n custom_dir = $22,\n prev_custom_dir = $23,\n migrated = $24\n ",
|
|
||||||
"describe": {
|
|
||||||
"columns": [],
|
|
||||||
"parameters": {
|
|
||||||
"Right": 24
|
|
||||||
},
|
|
||||||
"nullable": []
|
|
||||||
},
|
|
||||||
"hash": "d645daf951ff6fead3c86df685d99bacc81cb0a999c0f8d2ff7755b0089a79d8"
|
|
||||||
}
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "theseus"
|
name = "theseus"
|
||||||
version = "0.8.7"
|
version = "0.8.8"
|
||||||
authors = ["Jai A <jaiagr+gpg@pm.me>"]
|
authors = ["Jai A <jaiagr+gpg@pm.me>"]
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
@@ -36,7 +36,7 @@ tracing-error = "0.2.0"
|
|||||||
|
|
||||||
paste = { version = "1.0" }
|
paste = { version = "1.0" }
|
||||||
|
|
||||||
tauri = { git = "https://github.com/modrinth/tauri", rev = "5e29428", optional = true }
|
tauri = { version = "2.0.0-rc", optional = true }
|
||||||
indicatif = { version = "0.17.3", optional = true }
|
indicatif = { version = "0.17.3", optional = true }
|
||||||
|
|
||||||
async-tungstenite = { version = "0.27.0", features = ["tokio-runtime", "tokio-rustls-webpki-roots"] }
|
async-tungstenite = { version = "0.27.0", features = ["tokio-runtime", "tokio-rustls-webpki-roots"] }
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
ALTER TABLE settings ADD COLUMN personalized_ads INTEGER NOT NULL DEFAULT TRUE;
|
||||||
@@ -17,6 +17,7 @@ pub struct Settings {
|
|||||||
pub telemetry: bool,
|
pub telemetry: bool,
|
||||||
pub discord_rpc: bool,
|
pub discord_rpc: bool,
|
||||||
pub developer_mode: bool,
|
pub developer_mode: bool,
|
||||||
|
pub personalized_ads: bool,
|
||||||
|
|
||||||
pub onboarded: bool,
|
pub onboarded: bool,
|
||||||
|
|
||||||
@@ -42,7 +43,7 @@ impl Settings {
|
|||||||
SELECT
|
SELECT
|
||||||
max_concurrent_writes, max_concurrent_downloads,
|
max_concurrent_writes, max_concurrent_downloads,
|
||||||
theme, default_page, collapsed_navigation, advanced_rendering, native_decorations,
|
theme, default_page, collapsed_navigation, advanced_rendering, native_decorations,
|
||||||
discord_rpc, developer_mode, telemetry,
|
discord_rpc, developer_mode, telemetry, personalized_ads,
|
||||||
onboarded,
|
onboarded,
|
||||||
json(extra_launch_args) extra_launch_args, json(custom_env_vars) custom_env_vars,
|
json(extra_launch_args) extra_launch_args, json(custom_env_vars) custom_env_vars,
|
||||||
mc_memory_max, mc_force_fullscreen, mc_game_resolution_x, mc_game_resolution_y, hide_on_process_start,
|
mc_memory_max, mc_force_fullscreen, mc_game_resolution_x, mc_game_resolution_y, hide_on_process_start,
|
||||||
@@ -65,6 +66,7 @@ impl Settings {
|
|||||||
telemetry: res.telemetry == 1,
|
telemetry: res.telemetry == 1,
|
||||||
discord_rpc: res.discord_rpc == 1,
|
discord_rpc: res.discord_rpc == 1,
|
||||||
developer_mode: res.developer_mode == 1,
|
developer_mode: res.developer_mode == 1,
|
||||||
|
personalized_ads: res.personalized_ads == 1,
|
||||||
onboarded: res.onboarded == 1,
|
onboarded: res.onboarded == 1,
|
||||||
extra_launch_args: res
|
extra_launch_args: res
|
||||||
.extra_launch_args
|
.extra_launch_args
|
||||||
@@ -123,24 +125,25 @@ impl Settings {
|
|||||||
discord_rpc = $8,
|
discord_rpc = $8,
|
||||||
developer_mode = $9,
|
developer_mode = $9,
|
||||||
telemetry = $10,
|
telemetry = $10,
|
||||||
|
personalized_ads = $11,
|
||||||
|
|
||||||
onboarded = $11,
|
onboarded = $12,
|
||||||
|
|
||||||
extra_launch_args = jsonb($12),
|
extra_launch_args = jsonb($13),
|
||||||
custom_env_vars = jsonb($13),
|
custom_env_vars = jsonb($14),
|
||||||
mc_memory_max = $14,
|
mc_memory_max = $15,
|
||||||
mc_force_fullscreen = $15,
|
mc_force_fullscreen = $16,
|
||||||
mc_game_resolution_x = $16,
|
mc_game_resolution_x = $17,
|
||||||
mc_game_resolution_y = $17,
|
mc_game_resolution_y = $18,
|
||||||
hide_on_process_start = $18,
|
hide_on_process_start = $19,
|
||||||
|
|
||||||
hook_pre_launch = $19,
|
hook_pre_launch = $20,
|
||||||
hook_wrapper = $20,
|
hook_wrapper = $21,
|
||||||
hook_post_exit = $21,
|
hook_post_exit = $22,
|
||||||
|
|
||||||
custom_dir = $22,
|
custom_dir = $23,
|
||||||
prev_custom_dir = $23,
|
prev_custom_dir = $24,
|
||||||
migrated = $24
|
migrated = $25
|
||||||
",
|
",
|
||||||
max_concurrent_writes,
|
max_concurrent_writes,
|
||||||
max_concurrent_downloads,
|
max_concurrent_downloads,
|
||||||
@@ -152,6 +155,7 @@ impl Settings {
|
|||||||
self.discord_rpc,
|
self.discord_rpc,
|
||||||
self.developer_mode,
|
self.developer_mode,
|
||||||
self.telemetry,
|
self.telemetry,
|
||||||
|
self.personalized_ads,
|
||||||
self.onboarded,
|
self.onboarded,
|
||||||
extra_launch_args,
|
extra_launch_args,
|
||||||
custom_env_vars,
|
custom_env_vars,
|
||||||
|
|||||||
@@ -1,121 +0,0 @@
|
|||||||
<template>
|
|
||||||
<div class="GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD">
|
|
||||||
<a href="https://modrinth.com/plus" rel="noopener nofollow sponsored" :target="target"></a>
|
|
||||||
<div class="GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-0">
|
|
||||||
<div class="GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-1">
|
|
||||||
<div class="GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-2">
|
|
||||||
<ModrinthPlusIcon class="GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-3" />
|
|
||||||
<span>
|
|
||||||
<span>
|
|
||||||
90% of ad revenue goes to creators. Go ad-free while supporting creators with
|
|
||||||
</span>
|
|
||||||
<strong>Modrinth Plus.</strong>
|
|
||||||
<span> Subscribe today!</span>
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-4">
|
|
||||||
<a rel="noopener sponsored" :target="target" href="https://adrinth.com"> Ad via Adrinth </a>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<script setup lang="ts">
|
|
||||||
import { computed } from 'vue'
|
|
||||||
import { ModrinthPlusIcon } from '@modrinth/assets'
|
|
||||||
|
|
||||||
const props = withDefaults(
|
|
||||||
defineProps<{
|
|
||||||
external: boolean
|
|
||||||
}>(),
|
|
||||||
{
|
|
||||||
external: true,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
|
|
||||||
const target = computed(() => (props.external ? '_blank' : '_self'))
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD {
|
|
||||||
position: relative;
|
|
||||||
margin-bottom: var(--gap-md);
|
|
||||||
background: var(--color-ad);
|
|
||||||
border: 1px solid var(--color-ad-raised);
|
|
||||||
border-radius: var(--radius-lg);
|
|
||||||
container-type: inline-size;
|
|
||||||
width: 100%;
|
|
||||||
|
|
||||||
> a {
|
|
||||||
position: absolute;
|
|
||||||
inset: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
&:has(> a:first-child:active) {
|
|
||||||
scale: 0.99;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-0 {
|
|
||||||
font-size: 14px;
|
|
||||||
line-height: 1.3em;
|
|
||||||
}
|
|
||||||
.GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-1 {
|
|
||||||
color: var(--color-base);
|
|
||||||
padding: 1em;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-2 {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
color: var(--color-base);
|
|
||||||
margin-right: 7.5rem;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-2 b,
|
|
||||||
.GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-2 strong {
|
|
||||||
color: var(--color-ad-highlight);
|
|
||||||
}
|
|
||||||
.GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-3 {
|
|
||||||
padding-top: 1px;
|
|
||||||
height: 1.5rem;
|
|
||||||
width: auto;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
.GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-4 a {
|
|
||||||
position: absolute;
|
|
||||||
bottom: -1px;
|
|
||||||
right: -1px;
|
|
||||||
text-align: center;
|
|
||||||
font-weight: 600;
|
|
||||||
text-transform: uppercase;
|
|
||||||
font-size: 0.8em;
|
|
||||||
color: var(--color-ad-contrast);
|
|
||||||
background: var(--color-ad-raised);
|
|
||||||
letter-spacing: 0.1ch;
|
|
||||||
margin: 0;
|
|
||||||
padding: 2px 10px;
|
|
||||||
border-top-left-radius: var(--radius-lg);
|
|
||||||
border-bottom-right-radius: var(--radius-lg);
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
gap: 0.5rem;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
text-decoration: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@media screen and (max-width: 800px) {
|
|
||||||
.GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-2 {
|
|
||||||
margin-bottom: 0.5rem;
|
|
||||||
}
|
|
||||||
.GBBNWLJVGRHFLYVGSZKSSKNTHFYXHMBD-2 a {
|
|
||||||
align-items: flex-start;
|
|
||||||
flex-direction: column;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -540,8 +540,11 @@ async function refreshPayment(confirmationId, paymentMethodId) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const result = await props.sendBillingRequest({
|
const result = await props.sendBillingRequest({
|
||||||
product_id: props.product.id,
|
charge: {
|
||||||
interval: selectedPlan.value,
|
type: 'new',
|
||||||
|
product_id: props.product.id,
|
||||||
|
interval: selectedPlan.value,
|
||||||
|
},
|
||||||
existing_payment_intent: paymentIntentId.value,
|
existing_payment_intent: paymentIntentId.value,
|
||||||
...base,
|
...base,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -22,7 +22,6 @@ export { default as Page } from './base/Page.vue'
|
|||||||
export { default as Pagination } from './base/Pagination.vue'
|
export { default as Pagination } from './base/Pagination.vue'
|
||||||
export { default as PopoutMenu } from './base/PopoutMenu.vue'
|
export { default as PopoutMenu } from './base/PopoutMenu.vue'
|
||||||
export { default as ProjectCard } from './base/ProjectCard.vue'
|
export { default as ProjectCard } from './base/ProjectCard.vue'
|
||||||
export { default as Promotion } from './base/Promotion.vue'
|
|
||||||
export { default as ScrollablePanel } from './base/ScrollablePanel.vue'
|
export { default as ScrollablePanel } from './base/ScrollablePanel.vue'
|
||||||
export { default as Slider } from './base/Slider.vue'
|
export { default as Slider } from './base/Slider.vue'
|
||||||
export { default as StatItem } from './base/StatItem.vue'
|
export { default as StatItem } from './base/StatItem.vue'
|
||||||
|
|||||||
@@ -1,21 +1,21 @@
|
|||||||
import hljs from 'highlight.js/lib/core'
|
import hljs from 'highlight.js/lib/core'
|
||||||
// Scripting
|
// Scripting
|
||||||
import javascript from 'highlight.js/lib/languages/javascript'
|
import javascript from 'highlight.js/lib/languages/javascript'
|
||||||
import python from 'highlight.js/lib/languages/python'
|
|
||||||
import lua from 'highlight.js/lib/languages/lua'
|
import lua from 'highlight.js/lib/languages/lua'
|
||||||
|
import python from 'highlight.js/lib/languages/python'
|
||||||
// Coding
|
// Coding
|
||||||
|
import groovy from 'highlight.js/lib/languages/groovy'
|
||||||
import java from 'highlight.js/lib/languages/java'
|
import java from 'highlight.js/lib/languages/java'
|
||||||
import kotlin from 'highlight.js/lib/languages/kotlin'
|
import kotlin from 'highlight.js/lib/languages/kotlin'
|
||||||
import scala from 'highlight.js/lib/languages/scala'
|
import scala from 'highlight.js/lib/languages/scala'
|
||||||
import groovy from 'highlight.js/lib/languages/groovy'
|
|
||||||
// Configs
|
// Configs
|
||||||
import gradle from 'highlight.js/lib/languages/gradle'
|
import gradle from 'highlight.js/lib/languages/gradle'
|
||||||
import json from 'highlight.js/lib/languages/json'
|
|
||||||
import ini from 'highlight.js/lib/languages/ini'
|
import ini from 'highlight.js/lib/languages/ini'
|
||||||
import yaml from 'highlight.js/lib/languages/yaml'
|
import json from 'highlight.js/lib/languages/json'
|
||||||
import xml from 'highlight.js/lib/languages/xml'
|
|
||||||
import properties from 'highlight.js/lib/languages/properties'
|
import properties from 'highlight.js/lib/languages/properties'
|
||||||
import { md, configuredXss } from './parse'
|
import xml from 'highlight.js/lib/languages/xml'
|
||||||
|
import yaml from 'highlight.js/lib/languages/yaml'
|
||||||
|
import { configuredXss, md } from './parse'
|
||||||
|
|
||||||
/* REGISTRATION */
|
/* REGISTRATION */
|
||||||
// Scripting
|
// Scripting
|
||||||
@@ -54,7 +54,7 @@ export const renderHighlightedString = (string) =>
|
|||||||
if (lang && hljs.getLanguage(lang)) {
|
if (lang && hljs.getLanguage(lang)) {
|
||||||
try {
|
try {
|
||||||
return hljs.highlight(str, { language: lang }).value
|
return hljs.highlight(str, { language: lang }).value
|
||||||
} catch (__) {
|
} catch {
|
||||||
/* empty */
|
/* empty */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2
packages/utils/index.d.ts
vendored
2
packages/utils/index.d.ts
vendored
@@ -1,4 +1,4 @@
|
|||||||
const BASE62_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' as const
|
export const BASE62_CHARS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'
|
||||||
type Base62Char = (typeof BASE62_CHARS)[number]
|
type Base62Char = (typeof BASE62_CHARS)[number]
|
||||||
|
|
||||||
declare global {
|
declare global {
|
||||||
|
|||||||
@@ -77,7 +77,11 @@ export const configuredXss = new FilterXSS({
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
safeAttrValue(tag, name, value, cssFilter) {
|
safeAttrValue(tag, name, value, cssFilter) {
|
||||||
if (tag === 'img' && name === 'src' && !value.startsWith('data:')) {
|
if (
|
||||||
|
(tag === 'img' || tag === 'video' || tag === 'audio' || tag === 'source') &&
|
||||||
|
(name === 'src' || name === 'srcset') &&
|
||||||
|
!value.startsWith('data:')
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
const url = new URL(value)
|
const url = new URL(value)
|
||||||
|
|
||||||
@@ -112,7 +116,7 @@ export const configuredXss = new FilterXSS({
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
return safeAttrValue(tag, name, url.toString(), cssFilter)
|
return safeAttrValue(tag, name, url.toString(), cssFilter)
|
||||||
} catch (err) {
|
} catch {
|
||||||
/* empty */
|
/* empty */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,7 +153,7 @@ export const md = (options = {}) => {
|
|||||||
if (allowedHostnames.includes(url.hostname)) {
|
if (allowedHostnames.includes(url.hostname)) {
|
||||||
return defaultLinkOpenRenderer(tokens, idx, options, env, self)
|
return defaultLinkOpenRenderer(tokens, idx, options, env, self)
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch {
|
||||||
/* empty */
|
/* empty */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
2978
pnpm-lock.yaml
generated
2978
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user