You've already forked AstralRinth
forked from didirus/AstralRinth
@@ -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:
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -55,3 +55,6 @@ generated
|
|||||||
|
|
||||||
# app testing dir
|
# app testing dir
|
||||||
app-playground-data/*
|
app-playground-data/*
|
||||||
|
|
||||||
|
Cargo.lock
|
||||||
|
pnpm-lock.yaml
|
||||||
Generated
+385
-356
File diff suppressed because it is too large
Load Diff
+1
-2
@@ -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>
|
||||||
|
|||||||
+3
-3
@@ -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
+1384
-2319
File diff suppressed because it is too large
Load Diff
+1384
-2319
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": {
|
||||||
|
|||||||
@@ -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>
|
||||||
|
|||||||
Generated
+12
@@ -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"
|
||||||
|
}
|
||||||
+25
-19
@@ -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"
|
||||||
}
|
}
|
||||||
Generated
-12
@@ -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 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Vendored
+1
-1
@@ -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 */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Generated
+1541
-1437
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user