Sharing logs (#325)
* Sharing * Mod UI changes * Final touches * update UI * Run lint * Addressed changes
@@ -18,7 +18,7 @@
|
||||
"floating-vue": "^2.0.0-beta.20",
|
||||
"mixpanel-browser": "^2.47.0",
|
||||
"ofetch": "^1.0.1",
|
||||
"omorphia": "^0.4.31",
|
||||
"omorphia": "^0.4.33",
|
||||
"pinia": "^2.1.3",
|
||||
"tauri-plugin-window-state-api": "github:tauri-apps/tauri-plugin-window-state#v1",
|
||||
"vite-svg-loader": "^4.0.0",
|
||||
@@ -38,5 +38,5 @@
|
||||
"vite": "^4.3.9",
|
||||
"vite-plugin-eslint": "^1.8.1"
|
||||
},
|
||||
"packageManager": "pnpm@8.5.1"
|
||||
"packageManager": "pnpm@8.6.0"
|
||||
}
|
||||
|
||||
@@ -1,4 +1,8 @@
|
||||
lockfileVersion: '6.0'
|
||||
lockfileVersion: '6.1'
|
||||
|
||||
settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
dependencies:
|
||||
'@tauri-apps/api':
|
||||
@@ -17,14 +21,14 @@ dependencies:
|
||||
specifier: ^1.0.1
|
||||
version: 1.0.1
|
||||
omorphia:
|
||||
specifier: ^0.4.31
|
||||
version: 0.4.31
|
||||
specifier: ^0.4.33
|
||||
version: 0.4.33
|
||||
pinia:
|
||||
specifier: ^2.1.3
|
||||
version: 2.1.3(vue@3.3.4)
|
||||
tauri-plugin-window-state-api:
|
||||
specifier: github:tauri-apps/tauri-plugin-window-state#v1
|
||||
version: github.com/tauri-apps/tauri-plugin-window-state/56fd671f8d5ac2d8b826a358af486f220a125c3d
|
||||
version: github.com/tauri-apps/tauri-plugin-window-state/347c792535d2623fc21f66590d06f4c8dadd85ba
|
||||
vite-svg-loader:
|
||||
specifier: ^4.0.0
|
||||
version: 4.0.0
|
||||
@@ -409,6 +413,11 @@ packages:
|
||||
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
||||
dev: false
|
||||
|
||||
/@tauri-apps/api@1.4.0:
|
||||
resolution: {integrity: sha512-Jd6HPoTM1PZSFIzq7FB8VmMu3qSSyo/3lSwLpoapW+lQ41CL5Dow2KryLg+gyazA/58DRWI9vu/XpEeHK4uMdw==}
|
||||
engines: {node: '>= 14.6.0', npm: '>= 6.6.0', yarn: '>= 1.19.1'}
|
||||
dev: false
|
||||
|
||||
/@tauri-apps/cli-darwin-arm64@1.3.1:
|
||||
resolution: {integrity: sha512-QlepYVPgOgspcwA/u4kGG4ZUijlXfdRtno00zEy+LxinN/IRXtk+6ErVtsmoLi1ZC9WbuMwzAcsRvqsD+RtNAg==}
|
||||
engines: {node: '>= 10'}
|
||||
@@ -1336,13 +1345,14 @@ packages:
|
||||
ufo: 1.1.2
|
||||
dev: false
|
||||
|
||||
/omorphia@0.4.31:
|
||||
resolution: {integrity: sha512-xeb9bD42VFRDKCkKz678hBYCIS//Atd4/hx6/YmboJLMEIjIJfS2Ocf9G53G52XkfS4DWs9CIzKz71NDh86kxQ==}
|
||||
/omorphia@0.4.33:
|
||||
resolution: {integrity: sha512-Wo0t16zRL8ZLJSKVAYv6pdYhL4YXYjDYs18shO7V5cfxjcynvd5j0sui6uBR8ghVMWFEJH994AEC/urLwcHiBA==}
|
||||
dependencies:
|
||||
dayjs: 1.11.7
|
||||
floating-vue: 2.0.0-beta.20(vue@3.3.4)
|
||||
highlight.js: 11.8.0
|
||||
markdown-it: 13.0.1
|
||||
qrcode.vue: 3.4.0(vue@3.3.4)
|
||||
vue: 3.3.4
|
||||
vue-router: 4.2.1(vue@3.3.4)
|
||||
vue-select: 4.0.0-beta.6(vue@3.3.4)
|
||||
@@ -1460,6 +1470,14 @@ packages:
|
||||
engines: {node: '>=6'}
|
||||
dev: true
|
||||
|
||||
/qrcode.vue@3.4.0(vue@3.3.4):
|
||||
resolution: {integrity: sha512-4XeImbv10Fin16Fl2DArCMhGyAdvIg2jb7vDT+hZiIAMg/6H6mz9nUZr/dR8jBcun5VzNzkiwKhiqOGbloinwA==}
|
||||
peerDependencies:
|
||||
vue: ^3.0.0
|
||||
dependencies:
|
||||
vue: 3.3.4
|
||||
dev: false
|
||||
|
||||
/queue-microtask@1.2.3:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
dev: true
|
||||
@@ -1791,10 +1809,10 @@ packages:
|
||||
engines: {node: '>=10'}
|
||||
dev: true
|
||||
|
||||
github.com/tauri-apps/tauri-plugin-window-state/56fd671f8d5ac2d8b826a358af486f220a125c3d:
|
||||
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-window-state/tar.gz/56fd671f8d5ac2d8b826a358af486f220a125c3d}
|
||||
github.com/tauri-apps/tauri-plugin-window-state/347c792535d2623fc21f66590d06f4c8dadd85ba:
|
||||
resolution: {tarball: https://codeload.github.com/tauri-apps/tauri-plugin-window-state/tar.gz/347c792535d2623fc21f66590d06f4c8dadd85ba}
|
||||
name: tauri-plugin-window-state-api
|
||||
version: 0.0.0
|
||||
dependencies:
|
||||
'@tauri-apps/api': 1.3.0
|
||||
'@tauri-apps/api': 1.4.0
|
||||
dev: false
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg height="32" viewBox="0 0 32 32" width="32" xmlns="http://www.w3.org/2000/svg"><path d="m16 .396c-8.839 0-16 7.167-16 16 0 7.073 4.584 13.068 10.937 15.183.803.151 1.093-.344 1.093-.772 0-.38-.009-1.385-.015-2.719-4.453.964-5.391-2.151-5.391-2.151-.729-1.844-1.781-2.339-1.781-2.339-1.448-.989.115-.968.115-.968 1.604.109 2.448 1.645 2.448 1.645 1.427 2.448 3.744 1.74 4.661 1.328.14-1.031.557-1.74 1.011-2.135-3.552-.401-7.287-1.776-7.287-7.907 0-1.751.62-3.177 1.645-4.297-.177-.401-.719-2.031.141-4.235 0 0 1.339-.427 4.4 1.641 1.281-.355 2.641-.532 4-.541 1.36.009 2.719.187 4 .541 3.043-2.068 4.381-1.641 4.381-1.641.859 2.204.317 3.833.161 4.235 1.015 1.12 1.635 2.547 1.635 4.297 0 6.145-3.74 7.5-7.296 7.891.556.479 1.077 1.464 1.077 2.959 0 2.14-.02 3.864-.02 4.385 0 .416.28.916 1.104.755 6.4-2.093 10.979-8.093 10.979-15.156 0-8.833-7.161-16-16-16z"/></svg>
|
||||
|
After Width: | Height: | Size: 872 B |
@@ -4,3 +4,7 @@ export { default as KoFiIcon } from './kofi.svg'
|
||||
export { default as PatreonIcon } from './patreon.svg'
|
||||
export { default as PaypalIcon } from './paypal.svg'
|
||||
export { default as OpenCollectiveIcon } from './opencollective.svg'
|
||||
export { default as TwitterIcon } from './twitter.svg'
|
||||
export { default as GithubIcon } from './github.svg'
|
||||
export { default as MastodonIcon } from './mastodon.svg'
|
||||
export { default as RedditIcon } from './reddit.svg'
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M480,173.59c0-104.13-68.26-134.65-68.26-134.65C377.3,23.15,318.2,16.5,256.8,16h-1.51c-61.4.5-120.46,7.15-154.88,22.94,0,0-68.27,30.52-68.27,134.65,0,23.85-.46,52.35.29,82.59C34.91,358,51.11,458.37,145.32,483.29c43.43,11.49,80.73,13.89,110.76,12.24,54.47-3,85-19.42,85-19.42l-1.79-39.5s-38.93,12.27-82.64,10.77c-43.31-1.48-89-4.67-96-57.81a108.44,108.44,0,0,1-1-14.9,558.91,558.91,0,0,0,96.39,12.85c32.95,1.51,63.84-1.93,95.22-5.67,60.18-7.18,112.58-44.24,119.16-78.09C480.84,250.42,480,173.59,480,173.59ZM399.46,307.75h-50V185.38c0-25.8-10.86-38.89-32.58-38.89-24,0-36.06,15.53-36.06,46.24v67H231.16v-67c0-30.71-12-46.24-36.06-46.24-21.72,0-32.58,13.09-32.58,38.89V307.75h-50V181.67q0-38.65,19.75-61.39c13.6-15.15,31.4-22.92,53.51-22.92,25.58,0,44.95,9.82,57.75,29.48L256,147.69l12.45-20.85c12.81-19.66,32.17-29.48,57.75-29.48,22.11,0,39.91,7.77,53.51,22.92Q399.5,143,399.46,181.67Z"/></svg>
|
||||
|
After Width: | Height: | Size: 962 B |
@@ -0,0 +1 @@
|
||||
<svg id="Layer_1" enable-background="new 0 0 100 100" height="512" viewBox="0 0 100 100" width="512" xmlns="http://www.w3.org/2000/svg"><g id="_x33_2.Reddit"><path id="Icon_69_" d="m90 50.6c-.2-4.8-4.2-8.6-9.1-8.5-2.2.1-4.2 1-5.7 2.4-6.8-4.7-14.9-7.2-23.2-7.4l3.9-18.7 12.9 2.6c.4 3.3 3.3 5.7 6.6 5.3s5.7-3.3 5.3-6.6-3.3-5.7-6.6-5.3c-1.9.2-3.6 1.3-4.5 2.9l-14.7-2.9c-1-.2-2 .4-2.2 1.4l-4.4 20.9c-8.4.1-16.5 2.7-23.5 7.4-3.5-3.3-9.1-3.2-12.4.4-3.3 3.5-3.2 9.1.4 12.4.7.6 1.5 1.2 2.4 1.6-.1.9-.1 1.8 0 2.6 0 13.5 15.7 24.5 35.1 24.5s35.1-10.9 35.1-24.5c.1-.9.1-1.8 0-2.6 2.8-1.4 4.7-4.5 4.6-7.9zm-60.3 6.1c0-3.3 2.7-6 6-6s6 2.7 6 6-2.7 6-6 6-6-2.7-6-6zm35 16.6c-4.3 3.2-9.5 4.9-14.8 4.6-5.3.2-10.6-1.4-14.8-4.6-.6-.7-.5-1.7.2-2.3.6-.5 1.4-.5 2.1 0 3.6 2.6 8 4 12.5 3.8 4.5.2 8.9-1 12.6-3.7.7-.6 1.7-.6 2.4 0 .6.7.6 1.7 0 2.4v-.2zm-1-10.3c-3.3 0-6-2.7-6-6s2.7-6 6-6 6 2.7 6 6c.1 3.3-2.4 6.1-5.8 6.2-.1 0-.2 0-.3 0z"/></g></svg>
|
||||
|
After Width: | Height: | Size: 924 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--! Font Awesome Pro 6.4.0 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2023 Fonticons, Inc. --><path d="M459.37 151.716c.325 4.548.325 9.097.325 13.645 0 138.72-105.583 298.558-298.558 298.558-59.452 0-114.68-17.219-161.137-47.106 8.447.974 16.568 1.299 25.34 1.299 49.055 0 94.213-16.568 130.274-44.832-46.132-.975-84.792-31.188-98.112-72.772 6.498.974 12.995 1.624 19.818 1.624 9.421 0 18.843-1.3 27.614-3.573-48.081-9.747-84.143-51.98-84.143-102.985v-1.299c13.969 7.797 30.214 12.67 47.431 13.319-28.264-18.843-46.781-51.005-46.781-87.391 0-19.492 5.197-37.36 14.294-52.954 51.655 63.675 129.3 105.258 216.365 109.807-1.624-7.797-2.599-15.918-2.599-24.04 0-57.828 46.782-104.934 104.934-104.934 30.213 0 57.502 12.67 76.67 33.137 23.715-4.548 46.456-13.32 66.599-25.34-7.798 24.366-24.366 44.833-46.132 57.827 21.117-2.273 41.584-8.122 60.426-16.243-14.292 20.791-32.161 39.308-52.628 54.253z"/></svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 24 KiB |
@@ -2,5 +2,11 @@ export { default as ServerIcon } from './server.svg'
|
||||
export { default as MinimizeIcon } from './minimize.svg'
|
||||
export { default as MaximizeIcon } from './maximize.svg'
|
||||
export { default as SwapIcon } from './arrow-left-right.svg'
|
||||
export { default as ToggleIcon } from './toggle.svg'
|
||||
export { default as PackageIcon } from './package.svg'
|
||||
export { default as VersionIcon } from './milestone.svg'
|
||||
export { default as MoreIcon } from './more.svg'
|
||||
export { default as TextInputIcon } from './text-cursor-input.svg'
|
||||
export { default as AddProjectImage } from './add-project.svg'
|
||||
export { default as NewInstanceImage } from './new-instance.svg'
|
||||
export { default as MenuIcon } from './menu.svg'
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-menu"><line x1="4" x2="20" y1="12" y2="12"/><line x1="4" x2="20" y1="6" y2="6"/><line x1="4" x2="20" y1="18" y2="18"/></svg>
|
||||
|
After Width: | Height: | Size: 326 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-more-vertical"><circle cx="12" cy="12" r="1"/><circle cx="12" cy="5" r="1"/><circle cx="12" cy="19" r="1"/></svg>
|
||||
|
After Width: | Height: | Size: 315 B |
@@ -0,0 +1,138 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" data-name="Layer 1" width="924.76626" height="641.9894"
|
||||
viewBox="0 0 924.76626 641.9894" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<path
|
||||
d="M901.84039,677.83256c3.74046-30.07761,22.38093-59.7128,51.06588-69.50087a139.64665,139.64665,0,0,0,.00692,95.87682c4.40777,11.92286,10.55173,24.725,6.40563,36.74145-2.57964,7.477-8.89041,13.1975-15.94457,16.7744-7.0546,3.5769-14.88373,5.28172-22.61488,6.95243l-1.52153,1.25839C906.96476,738.22193,898.09992,707.91018,901.84039,677.83256Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#f0f0f0"/>
|
||||
<path
|
||||
d="M953.19092,608.90041a119.36031,119.36031,0,0,0-29.67278,67.17592,51.40093,51.40093,0,0,0,.58468,16.09418,29.48054,29.48054,0,0,0,7.33219,13.67368c3.30477,3.631,7.10567,6.96234,9.47027,11.33341a18.051,18.051,0,0,1,.88188,14.73616c-2.08769,5.98787-6.20242,10.86849-10.39214,15.50149-4.65189,5.14407-9.56524,10.41344-11.54265,17.23311-.23959.8263-1.50772.40622-1.26849-.41883,3.44035-11.865,14.95818-18.60464,20.451-29.29134,2.563-4.98661,3.63886-10.77584,1.236-16.03972-2.10117-4.603-6.01776-8.04173-9.39569-11.68923a31.458,31.458,0,0,1-7.66744-13.10281,47.51861,47.51861,0,0,1-1.20129-16.01232,115.8007,115.8007,0,0,1,8.45741-35.19088,121.4766,121.4766,0,0,1,21.84309-35.0047c.57116-.63958,1.45134.36648.88391,1.00188Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path
|
||||
d="M923.87771,667.99227a17.90785,17.90785,0,0,1-13.6314-18.75913c.06806-.85679,1.40267-.79127,1.33452.06666a16.58227,16.58227,0,0,0,12.71571,17.424c.83627.19883.41265,1.46618-.41883,1.26849Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path
|
||||
d="M929.51688,704.22384a34.51591,34.51591,0,0,0,15.41342-19.87863c.24251-.82542,1.51071-.4056,1.26849.41883A35.90175,35.90175,0,0,1,930.11768,705.417c-.74074.43939-1.33752-.75611-.6008-1.19312Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path
|
||||
d="M936.9349,631.34025a10.13673,10.13673,0,0,0,9.60617-.48764c.73481-.44857,1.33082.74746.6008,1.19311a11.359,11.359,0,0,1-10.6258.563.69037.69037,0,0,1-.42483-.84366.6713.6713,0,0,1,.84366-.42482Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path
|
||||
d="M1040.342,662.054c-.45086.29314-.90172.58628-1.35313.89071a133.49486,133.49486,0,0,0-17.06883,13.32611c-.41728.37207-.83456.75542-1.24028,1.13871a140.73351,140.73351,0,0,0-30.56436,41.83882,136.67119,136.67119,0,0,0-7.48626,19.36917c-2.76241,9.166-5.02827,19.324-10.4964,26.82144a23.44535,23.44535,0,0,1-1.82656,2.25485H920.89105c-.1123-.05636-.22516-.1015-.338-.15786l-1.973.09022c.07927-.3495.169-.71029.24827-1.05979.04514-.20293.1013-.40585.14644-.60878.03358-.13529.06771-.27064.09028-.39464.011-.04508.02257-.09015.03358-.124.02257-.124.0567-.23679.07927-.3495q.744-3.0271,1.53315-6.05427c0-.01129,0-.01129.011-.02257,4.04783-15.36682,9.41411-30.53071,16.91138-44.398.22571-.41714.45086-.84557.69914-1.26271a130.41346,130.41346,0,0,1,11.71411-17.76824,115.29059,115.29059,0,0,1,7.67783-8.78262,95.87273,95.87273,0,0,1,23.99138-17.97117c17.72338-9.35762,38.2422-12.94283,57.18328-7.22677C1039.38361,661.74961,1039.85759,661.89611,1040.342,662.054Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#f0f0f0"/>
|
||||
<path
|
||||
d="M1040.23094,662.68115a119.36024,119.36024,0,0,0-64.13659,35.77114,51.40084,51.40084,0,0,0-9.223,13.20232,29.48052,29.48052,0,0,0-2.37816,15.33216c.45258,4.88882,1.48168,9.83714.738,14.75085a18.051,18.051,0,0,1-8.168,12.297c-5.272,3.524-11.49586,4.94359-17.63051,6.12029-6.81135,1.30649-13.90692,2.55561-19.59168,6.8102-.68879.5155-1.4484-.58341-.76065-1.09813,9.89051-7.40226,23.14454-5.84891,33.96439-11.07458,5.04874-2.43839,9.39323-6.41306,10.64393-12.06264,1.09368-4.94031.03684-10.044-.4642-14.99a31.458,31.458,0,0,1,1.76676-15.07818,47.51855,47.51855,0,0,1,8.68137-13.5082,115.80059,115.80059,0,0,1,27.94011-23.006,121.4767,121.4767,0,0,1,38.51573-14.79824c.84111-.16679.93817,1.16642.10255,1.33212Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path
|
||||
d="M981.2486,692.21411A17.90784,17.90784,0,0,1,981.659,669.029c.57019-.64313,1.59636.21271,1.02541.85669a16.58227,16.58227,0,0,0-.33766,21.56781c.548.66224-.55326,1.4191-1.09813.76065Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path
|
||||
d="M963.93725,724.53816a34.51588,34.51588,0,0,0,24.27507-6.592c.69059-.513,1.45041.58571.76065,1.09813a35.90171,35.90171,0,0,1-25.27435,6.80826c-.856-.09514-.61271-1.409.23863-1.31436Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path
|
||||
d="M1013.74109,670.81085a10.13669,10.13669,0,0,0,7.96358,5.39423c.85677.08425.61256,1.39806-.23863,1.31436a11.359,11.359,0,0,1-8.82308-5.94794.69036.69036,0,0,1,.16874-.92939.67131.67131,0,0,1,.92939.16874Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path
|
||||
d="M742.23915,525.98269a10.0558,10.0558,0,0,0-1.61015-15.335l9.13555-34.54737-17.60072,5.92017-5.97689,31.89915a10.11027,10.11027,0,0,0,16.05221,12.06308Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#9e616a"/>
|
||||
<polygon points="686.055 629.029 673.795 629.028 667.963 581.74 686.057 581.741 686.055 629.029"
|
||||
fill="#9e616a"/>
|
||||
<path
|
||||
d="M826.79864,769.91783l-39.53076-.00146v-.5a15.38728,15.38728,0,0,1,15.38647-15.38623h.001l24.144.001Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#2f2e41"/>
|
||||
<polygon points="628.055 629.029 615.795 629.028 609.963 581.74 628.057 581.741 628.055 629.029"
|
||||
fill="#9e616a"/>
|
||||
<path
|
||||
d="M768.79864,769.91783l-39.53076-.00146v-.5a15.38728,15.38728,0,0,1,15.38647-15.38623h.001l24.144.001Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#2f2e41"/>
|
||||
<path id="b1d8f474-012b-4d97-a964-9f33bafc8058-812" data-name="Path 1095"
|
||||
d="M758.85336,473.11447l-4.706,1.3s-12.294,79.7-13.294,121.7,3,148,3,148h26l21-180,10,180h28s20-236,11-255S758.85336,473.11447,758.85336,473.11447Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#2f2e41"/>
|
||||
<circle id="e76160c9-f3a1-43ce-a248-d388186e85bb" data-name="Ellipse 219" cx="658.74398"
|
||||
cy="179.98357" r="23.49291" fill="#9e616a"/>
|
||||
<path id="bb67ace3-6b73-4a38-bac1-9d795c287a43-813" data-name="Path 1099"
|
||||
d="M855.85336,363.11447l-36.464-23.83-37.786,1.488-36.75,20.342,14,78-6,45s54-6,66,3a51.277,51.277,0,0,0,24,10l-2-77Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#3f3d56"/>
|
||||
<path id="f7a1be30-9471-4724-82e7-c8ff3c288394-814" data-name="Path 1101"
|
||||
d="M751.85336,360.11447l-3.778-.784-3.222,1.784s-9,12-9,23-11,117-11,117l20,9,16-83Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#3f3d56"/>
|
||||
<path id="a2423779-f29b-465e-aa9d-0fc12224f03e-815" data-name="Path 1104"
|
||||
d="M816.93427,291.7643s6.14449-11.74646-7.3736-12.81432c0,0-11.5243-10.454-23.27076-1.91114,0,0-6.40715,0-9.91084,7.25044,0,0-5.03919-1.91114-6.14657,3.20358,0,0-3.68733,10.67861,0,20.28934s4.91212,10.6786,4.91212,10.6786-6.059-20.14943,8.6892-21.21729,31.252-10.28455,32.48107,1.46189,3.07866,14.64066,3.07866,14.64066S831.06737,296.56968,816.93427,291.7643Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#2f2e41"/>
|
||||
<path id="e9616824-6bd8-4015-8eb7-3dcfe132b2c0-816" data-name="Subtraction 1"
|
||||
d="M513.35252,429.96937h-291v-218h291Z" transform="translate(-137.61687 -129.0053)"
|
||||
fill="#fff"/>
|
||||
<path id="f4711ed8-dad6-4be5-800d-5829f7fb3f37-817" data-name="Subtraction 1"
|
||||
d="M513.35252,429.96937h-291v-218h291Zm-288-215v212h285v-212Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#e6e6e6"/>
|
||||
<g id="b3812a0d-69b2-4ac3-87c4-e066c2de2dfd" data-name="Group 41">
|
||||
<circle id="fb0bff05-a63a-421c-8737-de050f830f30" data-name="Ellipse 220" cx="230.14466"
|
||||
cy="192.37305" r="55.409" fill="var(--color-green)"/>
|
||||
<path id="f9b355f0-5797-4243-8ae5-6fe77774d21b-818" data-name="Path 1106"
|
||||
d="M390.77053,316.72537h-18.839v-18.839a4.433,4.433,0,0,0-4.433-4.433h0a4.433,4.433,0,0,0-4.433,4.433v18.839h-18.839a4.433,4.433,0,0,0-4.433,4.433v0h0a4.433,4.433,0,0,0,4.433,4.433h18.839v18.839a4.433,4.433,0,0,0,4.433,4.433h0a4.433,4.433,0,0,0,4.433-4.433V325.59137h18.839a4.433,4.433,0,0,0,4.433-4.433v0h0a4.433,4.433,0,0,0-4.433-4.433h0Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
</g>
|
||||
<path d="M246.35588,211.0595h-108.739V129.0053h108.739Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path d="M246.35588,211.0595h-108.739V129.0053h108.739Zm-106.739-2h104.739V131.0053h-104.739Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#e6e6e6"/>
|
||||
<rect id="a0756b3d-8076-4d61-8f2c-cdb882ad5331" data-name="Rectangle 342" x="14.34201"
|
||||
y="22.34808" width="80.054" height="5.337" fill="#e4e4e4"/>
|
||||
<rect id="b5dd6458-8ffa-4f7b-ade4-3f6bf4de284a" data-name="Rectangle 343" x="14.34201"
|
||||
y="38.35803" width="80.054" height="5.337" fill="#e4e4e4"/>
|
||||
<rect id="bf0c907d-dbb4-4364-8cdd-63eed4118a99" data-name="Rectangle 344" x="14.34201"
|
||||
y="54.36908" width="80.054" height="5.337" fill="#e4e4e4"/>
|
||||
<path d="M969.35588,770.0595h-108.739V688.0053h108.739Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path d="M969.35588,770.0595h-108.739V688.0053h108.739Zm-106.739-2h104.739V690.0053h-104.739Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#e6e6e6"/>
|
||||
<rect id="b0c2ce11-0b20-4ceb-9ae2-a734f04b6c4a" data-name="Rectangle 342" x="737.34201"
|
||||
y="581.34808" width="80.054" height="5.337" fill="#e4e4e4"/>
|
||||
<rect id="bf5a9fda-652f-454e-a316-4f0fe63005cd" data-name="Rectangle 343" x="737.34201"
|
||||
y="597.35803" width="80.054" height="5.337" fill="#e4e4e4"/>
|
||||
<rect id="ad5f030a-4549-4063-8a1c-b5f384f37057" data-name="Rectangle 344" x="737.34201"
|
||||
y="613.36908" width="80.054" height="5.337" fill="#e4e4e4"/>
|
||||
<path d="M903.31826,622.82706l-81.22118-72.3,54.55741-61.28931,81.22119,72.3Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path
|
||||
d="M903.31826,622.82706l-81.22118-72.3,54.55741-61.28931,81.22119,72.3ZM824.92074,550.363l78.23344,69.64043L955.052,561.70184,876.81858,492.0614Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#e6e6e6"/>
|
||||
<rect id="b060c16b-2eb9-48d7-8f6b-fd5295a89bd0" data-name="Rectangle 342" x="897.96282"
|
||||
y="504.04622" width="5.337" height="80.054"
|
||||
transform="translate(-242.1991 726.03121) rotate(-48.32574)" fill="#e4e4e4"/>
|
||||
<rect id="aedfd2a5-e201-47b6-a3ec-b56955ab97bd" data-name="Rectangle 343" x="887.31788"
|
||||
y="516.00464" width="5.337" height="80.054"
|
||||
transform="translate(-254.69846 722.08744) rotate(-48.32574)" fill="#e4e4e4"/>
|
||||
<rect id="b4720297-2a1d-43a8-8ac0-2a4c1ee9f1d2" data-name="Rectangle 344" x="876.67222"
|
||||
y="527.96389" width="5.337" height="80.054"
|
||||
transform="translate(-267.19868 718.1434) rotate(-48.32574)" fill="#e4e4e4"/>
|
||||
<path d="M307.92339,259.0595H186.61687V167.52189H307.92339Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path
|
||||
d="M307.92339,259.0595H186.61687V167.52189H307.92339ZM188.848,256.82835H305.69224V169.753H188.848Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#e6e6e6"/>
|
||||
<rect id="e724a003-6a25-4c83-be10-32efc1fd30bf" data-name="Rectangle 342" x="64.99958"
|
||||
y="63.44755" width="89.30624" height="5.95382" fill="var(--color-green)"/>
|
||||
<rect id="f16e8690-23eb-4802-9b18-78b8e9972275" data-name="Rectangle 343" x="64.99958"
|
||||
y="81.30785" width="89.30624" height="5.95382" fill="var(--color-green)"/>
|
||||
<rect id="ea05cbc1-1ae7-4cbc-994d-a1c0c2d5941e" data-name="Rectangle 344" x="64.99958"
|
||||
y="99.16937" width="89.30624" height="5.95382" fill="var(--color-green)"/>
|
||||
<path d="M622.73338,498.69378H437.61687V359.0053H622.73338Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#fff"/>
|
||||
<path
|
||||
d="M622.73338,498.69378H437.61687V359.0053H622.73338ZM441.02166,495.289H619.3286V362.41009H441.02166Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#e6e6e6"/>
|
||||
<rect id="ac8b6f6a-33b0-4e01-bc67-8452ca74a9e6" data-name="Rectangle 342" x="324.41573"
|
||||
y="268.04521" width="136.28335" height="9.08567" fill="var(--color-green)"/>
|
||||
<rect id="e4f43daa-ee47-4f01-aaaf-288902bf6f27" data-name="Rectangle 343" x="324.41573"
|
||||
y="295.30043" width="136.28335" height="9.08567" fill="var(--color-green)"/>
|
||||
<rect id="b40e1bee-dfb3-4798-af30-e469c9a00d65" data-name="Rectangle 344" x="324.41573"
|
||||
y="322.55752" width="136.28335" height="9.08567" fill="var(--color-green)"/>
|
||||
<path
|
||||
d="M1061.19244,770.9947h-480.294a1.19069,1.19069,0,0,1,0-2.38137h480.294a1.19068,1.19068,0,1,1,0,2.38137Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#cacaca"/>
|
||||
<path
|
||||
d="M843.422,525.22926a10.05578,10.05578,0,0,1,5.50137-14.40454l.06041-35.73479,15.48506,10.24922-2.43139,32.363a10.11028,10.11028,0,0,1-18.61545,7.52706Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#9e616a"/>
|
||||
<path id="b2a3d507-71c0-44dd-96fb-9359ee9fed80-819" data-name="Path 1100"
|
||||
d="M844.85336,367.11447l6.918-6.668,5.082,3.668s5,6,9,24,0,117,0,117l-22-3,3-52-9-44Z"
|
||||
transform="translate(-137.61687 -129.0053)" fill="#3f3d56"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 13 KiB |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-text-cursor-input"><path d="M5 4h1a3 3 0 0 1 3 3 3 3 0 0 1 3-3h1"/><path d="M13 20h-1a3 3 0 0 1-3-3 3 3 0 0 1-3 3H5"/><path d="M5 16H4a2 2 0 0 1-2-2v-4a2 2 0 0 1 2-2h1"/><path d="M13 8h7a2 2 0 0 1 2 2v4a2 2 0 0 1-2 2h-7"/><path d="M9 7v10"/></svg>
|
||||
|
After Width: | Height: | Size: 449 B |
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="lucide lucide-toggle-right"><rect width="20" height="12" x="2" y="6" rx="6" ry="6"/><circle cx="16" cy="12" r="2"/></svg>
|
||||
|
After Width: | Height: | Size: 309 B |
@@ -57,3 +57,13 @@ export const installVersionDependencies = async (profile, version) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const openLink = (url) => {
|
||||
window.__TAURI_INVOKE__('tauri', {
|
||||
__tauriModule: 'Shell',
|
||||
message: {
|
||||
cmd: 'open',
|
||||
path: url,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ import { useRoute } from 'vue-router'
|
||||
import { useBreadcrumbs } from '@/store/breadcrumbs'
|
||||
import { profile_listener } from '@/helpers/events.js'
|
||||
import { handleError } from '@/store/notifications.js'
|
||||
import { Button, PlusIcon } from 'omorphia'
|
||||
import InstanceCreationModal from '@/components/ui/InstanceCreationModal.vue'
|
||||
import { NewInstanceImage } from '@/assets/icons'
|
||||
|
||||
const route = useRoute()
|
||||
const breadcrumbs = useBreadcrumbs()
|
||||
@@ -23,7 +26,23 @@ onUnmounted(() => unlisten())
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<GridDisplay label="Instances" :instances="instances" class="display" />
|
||||
<GridDisplay
|
||||
v-if="instances.length > 0"
|
||||
label="Instances"
|
||||
:instances="instances"
|
||||
class="display"
|
||||
/>
|
||||
<div v-else class="no-instance">
|
||||
<div class="icon">
|
||||
<NewInstanceImage />
|
||||
</div>
|
||||
<h3>No instances found</h3>
|
||||
<Button color="primary" @click="$refs.installationModal.show()">
|
||||
<PlusIcon />
|
||||
Create new instance
|
||||
</Button>
|
||||
<InstanceCreationModal ref="installationModal" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
@@ -31,4 +50,25 @@ onUnmounted(() => unlisten())
|
||||
background-color: rgb(30, 31, 34);
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.no-instance {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
height: 100%;
|
||||
gap: var(--gap-md);
|
||||
|
||||
p,
|
||||
h3 {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.icon {
|
||||
svg {
|
||||
width: 10rem;
|
||||
height: 10rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -101,6 +101,17 @@
|
||||
<template #open_folder> <ClipboardCopyIcon /> Open Folder </template>
|
||||
<template #copy_link> <ClipboardCopyIcon /> Copy Link </template>
|
||||
<template #open_link> <ClipboardCopyIcon /> Open In Modrinth <ExternalIcon /> </template>
|
||||
<template #copy_names><EditIcon />Copy names</template>
|
||||
<template #copy_slugs><HashIcon />Copy slugs</template>
|
||||
<template #copy_links><GlobeIcon />Copy Links</template>
|
||||
<template #toggle><EditIcon />Toggle selected</template>
|
||||
<template #disable><XIcon />Disable selected</template>
|
||||
<template #enable><CheckCircleIcon />Enable selected</template>
|
||||
<template #hide_show><EyeIcon />Show/Hide unselected</template>
|
||||
<template #update_all
|
||||
><UpdatedIcon />Update {{ selected.length > 0 ? 'selected' : 'all' }}</template
|
||||
>
|
||||
<template #filter_update><UpdatedIcon />Select Updatable</template>
|
||||
</ContextMenu>
|
||||
<ExportModal ref="exportModal" :instance="instance" />
|
||||
</template>
|
||||
@@ -120,6 +131,12 @@ import {
|
||||
ClipboardCopyIcon,
|
||||
PlusIcon,
|
||||
ExternalIcon,
|
||||
HashIcon,
|
||||
GlobeIcon,
|
||||
EyeIcon,
|
||||
XIcon,
|
||||
CheckCircleIcon,
|
||||
UpdatedIcon,
|
||||
} from 'omorphia'
|
||||
import { get, run } from '@/helpers/profile'
|
||||
import {
|
||||
@@ -340,6 +357,7 @@ Button {
|
||||
flex-direction: row;
|
||||
overflow: auto;
|
||||
gap: 1rem;
|
||||
min-height: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
<CheckIcon v-else />
|
||||
{{ copied ? 'Copied' : 'Copy' }}
|
||||
</Button>
|
||||
<Button disabled color="primary">
|
||||
<SendIcon />
|
||||
<Button color="primary" @click="share">
|
||||
<ShareIcon />
|
||||
Share
|
||||
</Button>
|
||||
<Button
|
||||
@@ -38,6 +38,13 @@
|
||||
{{ line }} <br />
|
||||
</span>
|
||||
</div>
|
||||
<ShareModal
|
||||
ref="shareModal"
|
||||
header="Share Log"
|
||||
share-title="Instance Log"
|
||||
share-text="Check out this log from an instance on the Modrinth App"
|
||||
link
|
||||
/>
|
||||
</Card>
|
||||
</template>
|
||||
|
||||
@@ -48,8 +55,9 @@ import {
|
||||
CheckIcon,
|
||||
ClipboardCopyIcon,
|
||||
DropdownSelect,
|
||||
SendIcon,
|
||||
ShareIcon,
|
||||
TrashIcon,
|
||||
ShareModal,
|
||||
} from 'omorphia'
|
||||
import { delete_logs_by_datetime, get_logs, get_output_by_datetime } from '@/helpers/logs.js'
|
||||
import { nextTick, onBeforeUnmount, onMounted, onUnmounted, ref, watch } from 'vue'
|
||||
@@ -59,6 +67,7 @@ import { get_output_by_uuid, get_uuids_by_profile_path } from '@/helpers/process
|
||||
import { useRoute } from 'vue-router'
|
||||
import { process_listener } from '@/helpers/events.js'
|
||||
import { handleError } from '@/store/notifications.js'
|
||||
import { ofetch } from 'ofetch'
|
||||
|
||||
dayjs.extend(calendar)
|
||||
|
||||
@@ -71,6 +80,17 @@ const props = defineProps({
|
||||
},
|
||||
})
|
||||
|
||||
const logs = ref([])
|
||||
await setLogs()
|
||||
|
||||
const selectedLogIndex = ref(0)
|
||||
const copied = ref(false)
|
||||
const logContainer = ref(null)
|
||||
const interval = ref(null)
|
||||
const userScrolled = ref(false)
|
||||
const isAutoScrolling = ref(false)
|
||||
const shareModal = ref(null)
|
||||
|
||||
async function getLiveLog() {
|
||||
if (route.params.id) {
|
||||
const uuids = await get_uuids_by_profile_path(route.params.id).catch(handleError)
|
||||
@@ -101,12 +121,6 @@ async function setLogs() {
|
||||
logs.value = [liveLog, ...allLogs]
|
||||
}
|
||||
|
||||
const logs = ref([])
|
||||
await setLogs()
|
||||
|
||||
const selectedLogIndex = ref(0)
|
||||
const copied = ref(false)
|
||||
|
||||
const copyLog = () => {
|
||||
if (logs.value[selectedLogIndex.value]) {
|
||||
navigator.clipboard.writeText(logs.value[selectedLogIndex.value].stdout)
|
||||
@@ -114,6 +128,20 @@ const copyLog = () => {
|
||||
}
|
||||
}
|
||||
|
||||
const share = async () => {
|
||||
if (logs.value[selectedLogIndex.value]) {
|
||||
const url = await ofetch('https://api.mclo.gs/1/log', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
},
|
||||
body: `content=${encodeURIComponent(logs.value[selectedLogIndex.value].stdout)}`,
|
||||
}).catch(handleError)
|
||||
|
||||
shareModal.value.show(url.url)
|
||||
}
|
||||
}
|
||||
|
||||
watch(selectedLogIndex, async (newIndex) => {
|
||||
copied.value = false
|
||||
userScrolled.value = false
|
||||
@@ -143,11 +171,6 @@ const deleteLog = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
const logContainer = ref(null)
|
||||
const interval = ref(null)
|
||||
const userScrolled = ref(false)
|
||||
const isAutoScrolling = ref(false)
|
||||
|
||||
function handleUserScroll() {
|
||||
if (!isAutoScrolling.value) {
|
||||
userScrolled.value = true
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
<template>
|
||||
<Card class="mod-card">
|
||||
<Card v-if="projects.length > 0" class="mod-card">
|
||||
<div class="second-row">
|
||||
<Chips
|
||||
v-if="Object.keys(selectableProjectTypes).length > 1"
|
||||
v-model="selectedProjectType"
|
||||
:items="Object.keys(selectableProjectTypes)"
|
||||
/>
|
||||
</div>
|
||||
<div class="card-row">
|
||||
<div class="iconified-input">
|
||||
<SearchIcon />
|
||||
@@ -18,16 +25,6 @@
|
||||
</Button>
|
||||
</div>
|
||||
<span class="manage">
|
||||
<span class="text-combo">
|
||||
<span class="no-wrap sort"> Sort by </span>
|
||||
<DropdownSelect
|
||||
v-model="sortFilter"
|
||||
name="sort-by"
|
||||
:options="['Name', 'Version', 'Author', 'Enabled']"
|
||||
default-value="Name"
|
||||
class="dropdown"
|
||||
/>
|
||||
</span>
|
||||
<DropdownButton
|
||||
:options="['search', 'from_file']"
|
||||
default-value="search"
|
||||
@@ -46,84 +43,132 @@
|
||||
</DropdownButton>
|
||||
</span>
|
||||
</div>
|
||||
<div class="second-row">
|
||||
<Chips
|
||||
v-if="Object.keys(selectableProjectTypes).length > 1"
|
||||
v-model="selectedProjectType"
|
||||
:items="Object.keys(selectableProjectTypes)"
|
||||
/>
|
||||
<DropdownButton
|
||||
:options="['update_all', 'filter_update']"
|
||||
default-value="update_all"
|
||||
:disabled="!projects.some((x) => x.outdated)"
|
||||
name="update-all-dropdown"
|
||||
@option-click="updateAll"
|
||||
>
|
||||
<template #update_all>
|
||||
<UpdatedIcon />
|
||||
Update {{ selected.length > 0 ? 'selected' : 'all' }}
|
||||
</template>
|
||||
<template #filter_update>
|
||||
<UpdatedIcon />
|
||||
Select updatable
|
||||
</template>
|
||||
</DropdownButton>
|
||||
<Button v-if="selected.length > 0" class="no-wrap" @click="deleteWarning.show()">
|
||||
<TrashIcon />
|
||||
Remove selected
|
||||
</Button>
|
||||
<DropdownButton
|
||||
v-if="selected.length > 0"
|
||||
:options="['toggle', 'disable', 'enable', 'hide_show']"
|
||||
default-value="toggle"
|
||||
@option-click="toggleSelected"
|
||||
>
|
||||
<template #toggle>
|
||||
<EditIcon />
|
||||
Toggle selected
|
||||
</template>
|
||||
<template #disable>
|
||||
<XIcon />
|
||||
Disable selected
|
||||
</template>
|
||||
<template #enable>
|
||||
<CheckCircleIcon />
|
||||
Enable selected
|
||||
</template>
|
||||
<template #hide_show>
|
||||
<CheckCircleIcon />
|
||||
{{ hideNonSelected ? 'Show' : 'Hide' }} unselected
|
||||
</template>
|
||||
</DropdownButton>
|
||||
<DropdownButton
|
||||
v-if="selected.length > 0"
|
||||
:options="['copy_name', 'copy_url', 'copy_slug']"
|
||||
default-value="copy_name"
|
||||
@option-click="copySelected"
|
||||
>
|
||||
<template #copy_name>
|
||||
<EditIcon />
|
||||
Copy names
|
||||
</template>
|
||||
<template #copy_slug>
|
||||
<HashIcon />
|
||||
Copy slugs
|
||||
</template>
|
||||
<template #copy_url>
|
||||
<GlobeIcon />
|
||||
Copy URLs
|
||||
</template>
|
||||
</DropdownButton>
|
||||
</div>
|
||||
<div>
|
||||
<div class="table">
|
||||
<div class="table-row table-head">
|
||||
<div class="table-row table-head" :class="{ 'show-options': selected.length > 0 }">
|
||||
<div class="table-cell table-text">
|
||||
<Checkbox v-model="selectAll" class="select-checkbox" />
|
||||
</div>
|
||||
<div class="table-cell table-text name-cell">Name</div>
|
||||
<div class="table-cell table-text">Version</div>
|
||||
<div class="table-cell table-text">Author</div>
|
||||
<div class="table-cell table-text">Actions</div>
|
||||
<div v-if="selected.length === 0" class="table-cell table-text name-cell actions-cell">
|
||||
<Button class="transparent" @click="sortProjects('Name')">
|
||||
Name
|
||||
<DropdownIcon v-if="sortColumn === 'Name'" :class="{ down: ascending }" />
|
||||
</Button>
|
||||
</div>
|
||||
<div v-if="selected.length === 0" class="table-cell table-text">
|
||||
<Button class="transparent" @click="sortProjects('Version')">
|
||||
Version
|
||||
<DropdownIcon v-if="sortColumn === 'Version'" :class="{ down: ascending }" />
|
||||
</Button>
|
||||
</div>
|
||||
<div v-if="selected.length === 0" class="table-cell table-text">
|
||||
<Button class="transparent" @click="sortProjects('Author')">
|
||||
Author
|
||||
<DropdownIcon v-if="sortColumn === 'Author'" :class="{ down: ascending }" />
|
||||
</Button>
|
||||
</div>
|
||||
<div v-if="selected.length === 0" class="table-cell table-text actions-cell">
|
||||
<Button class="transparent" @click="sortProjects('Enabled')">
|
||||
Actions
|
||||
<DropdownIcon v-if="sortColumn === 'Enabled'" :class="{ down: ascending }" />
|
||||
</Button>
|
||||
</div>
|
||||
<div v-else class="options table-cell name-cell">
|
||||
<Button
|
||||
class="transparent share"
|
||||
@click="() => (showingOptions = !showingOptions)"
|
||||
@mouseover="selectedOption = 'Share'"
|
||||
>
|
||||
<MenuIcon :class="{ open: showingOptions }" />
|
||||
</Button>
|
||||
<Button
|
||||
class="transparent share"
|
||||
@click="shareNames()"
|
||||
@mouseover="selectedOption = 'Share'"
|
||||
>
|
||||
<ShareIcon />
|
||||
Share
|
||||
</Button>
|
||||
<Button
|
||||
class="transparent trash"
|
||||
@click="deleteWarning.show()"
|
||||
@mouseover="selectedOption = 'Delete'"
|
||||
>
|
||||
<TrashIcon />
|
||||
Delete
|
||||
</Button>
|
||||
<Button
|
||||
class="transparent update"
|
||||
@click="updateAll()"
|
||||
@mouseover="selectedOption = 'Update'"
|
||||
>
|
||||
<UpdatedIcon />
|
||||
Update
|
||||
</Button>
|
||||
<Button
|
||||
class="transparent"
|
||||
@click="toggleSelected()"
|
||||
@mouseover="selectedOption = 'Toggle'"
|
||||
>
|
||||
<ToggleIcon />
|
||||
Toggle
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
<div v-if="showingOptions && selected.length > 0" class="more-box">
|
||||
<section v-if="selectedOption === 'Share'" class="options">
|
||||
<Button class="transparent" @click="shareNames()">
|
||||
<TextInputIcon />
|
||||
Share names
|
||||
</Button>
|
||||
<Button class="transparent" @click="shareUrls()">
|
||||
<GlobeIcon />
|
||||
Share URLs
|
||||
</Button>
|
||||
<Button class="transparent" @click="shareFileNames()">
|
||||
<FileIcon />
|
||||
Share file names
|
||||
</Button>
|
||||
<Button class="transparent" @click="shareMarkdown()">
|
||||
<CodeIcon />
|
||||
Share as markdown
|
||||
</Button>
|
||||
</section>
|
||||
<section v-if="selectedOption === 'Delete'" class="options">
|
||||
<Button class="transparent" @click="deleteWarning.show()">
|
||||
<TrashIcon />
|
||||
Delete selected
|
||||
</Button>
|
||||
<Button class="transparent" @click="deleteDisabledWarning.show()">
|
||||
<ToggleIcon />
|
||||
Delete disabled
|
||||
</Button>
|
||||
</section>
|
||||
<section v-if="selectedOption === 'Update'" class="options">
|
||||
<Button class="transparent" @click="updateAll()">
|
||||
<UpdatedIcon />
|
||||
Update all
|
||||
</Button>
|
||||
<Button class="transparent" @click="selectUpdatable()">
|
||||
<CheckIcon />
|
||||
Select updatable
|
||||
</Button>
|
||||
</section>
|
||||
<section v-if="selectedOption === 'Toggle'" class="options">
|
||||
<Button class="transparent" @click="enableAll()">
|
||||
<CheckIcon />
|
||||
Toggle on
|
||||
</Button>
|
||||
<Button class="transparent" @click="disableAll()">
|
||||
<XIcon />
|
||||
Toggle off
|
||||
</Button>
|
||||
<Button class="transparent" @click="hideShowAll()">
|
||||
<EyeIcon v-if="hideNonSelected" />
|
||||
<EyeOffIcon v-else />
|
||||
{{ hideNonSelected ? 'Show' : 'Hide' }} untoggled
|
||||
</Button>
|
||||
</section>
|
||||
</div>
|
||||
<div
|
||||
v-for="mod in search"
|
||||
@@ -132,7 +177,11 @@
|
||||
@contextmenu.prevent.stop="(c) => handleRightClick(c, mod)"
|
||||
>
|
||||
<div class="table-cell table-text">
|
||||
<Checkbox v-model="mod.selected" class="select-checkbox" />
|
||||
<Checkbox
|
||||
:model-value="selectionMap.get(mod.path)"
|
||||
class="select-checkbox"
|
||||
@update:model-value="(newValue) => selectionMap.set(mod.path, newValue)"
|
||||
/>
|
||||
</div>
|
||||
<div class="table-cell table-text name-cell">
|
||||
<router-link
|
||||
@@ -154,30 +203,64 @@
|
||||
<Button v-tooltip="'Remove project'" icon-only @click="removeMod(mod)">
|
||||
<TrashIcon />
|
||||
</Button>
|
||||
<AnimatedLogo v-if="mod.updating" class="btn icon-only updating-indicator"></AnimatedLogo>
|
||||
<Button v-else :disabled="!mod.outdated" icon-only @click="updateProject(mod)">
|
||||
<UpdatedIcon v-if="mod.outdated" v-tooltip="'Update project'" />
|
||||
<CheckIcon v-else v-tooltip="'Updated'" />
|
||||
<AnimatedLogo
|
||||
v-if="mod.updating"
|
||||
class="btn icon-only updating-indicator"
|
||||
></AnimatedLogo>
|
||||
<Button
|
||||
v-else
|
||||
v-tooltip="'Update project'"
|
||||
:disabled="!mod.outdated"
|
||||
icon-only
|
||||
@click="updateProject(mod)"
|
||||
>
|
||||
<UpdatedIcon v-if="mod.outdated" />
|
||||
<CheckIcon v-else />
|
||||
</Button>
|
||||
<input
|
||||
id="switch-1"
|
||||
autocomplete="off"
|
||||
type="checkbox"
|
||||
class="switch stylized-toggle"
|
||||
:disabled="mod.toggleInProgress"
|
||||
:checked="!mod.disabled"
|
||||
@change="toggleDisableMod(mod)"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</Card>
|
||||
<div v-else class="empty-prompt">
|
||||
<div class="empty-icon">
|
||||
<AddProjectImage />
|
||||
</div>
|
||||
<h3>No projects found</h3>
|
||||
<p class="empty-subtitle">Add a project to get started</p>
|
||||
<div class="empty-action">
|
||||
<DropdownButton
|
||||
:options="['search', 'from_file']"
|
||||
default-value="search"
|
||||
name="add-content-dropdown-from-empty"
|
||||
color="primary"
|
||||
@option-click="handleContentOptionClick"
|
||||
>
|
||||
<template #search>
|
||||
<SearchIcon />
|
||||
<span class="no-wrap"> Add content </span>
|
||||
</template>
|
||||
<template #from_file>
|
||||
<FolderOpenIcon />
|
||||
<span class="no-wrap"> Add from file </span>
|
||||
</template>
|
||||
</DropdownButton>
|
||||
</div>
|
||||
</div>
|
||||
<Modal ref="deleteWarning" header="Are you sure?">
|
||||
<div class="modal-body">
|
||||
<div class="markdown-body">
|
||||
<p>
|
||||
Are you sure you want to remove <strong>{{ selected.length }} projects</strong> from
|
||||
{{ instance.metadata.name }}?
|
||||
Are you sure you want to remove
|
||||
<strong>{{ functionValues.length }} project(s)</strong> from {{ instance.metadata.name }}?
|
||||
<br />
|
||||
This action <strong>cannot</strong> be undone.
|
||||
</p>
|
||||
@@ -191,6 +274,34 @@
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<Modal ref="deleteDisabledWarning" header="Are you sure?">
|
||||
<div class="modal-body">
|
||||
<div class="markdown-body">
|
||||
<p>
|
||||
Are you sure you want to remove
|
||||
<strong
|
||||
>{{ Array.from(projects.values()).filter((x) => x.disabled).length }} disabled
|
||||
project(s)</strong
|
||||
>
|
||||
from {{ instance.metadata.name }}?
|
||||
<br />
|
||||
This action <strong>cannot</strong> be undone.
|
||||
</p>
|
||||
</div>
|
||||
<div class="button-group push-right">
|
||||
<Button @click="deleteDisabledWarning.hide()"> Cancel </Button>
|
||||
<Button color="danger" @click="deleteDisabled">
|
||||
<TrashIcon />
|
||||
Remove
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<ShareModal
|
||||
ref="shareModal"
|
||||
share-title="Sharing modpack content"
|
||||
share-text="Check out the projects I'm using in my modpack!"
|
||||
/>
|
||||
</template>
|
||||
<script setup>
|
||||
import {
|
||||
@@ -201,19 +312,22 @@ import {
|
||||
CheckIcon,
|
||||
SearchIcon,
|
||||
UpdatedIcon,
|
||||
DropdownSelect,
|
||||
AnimatedLogo,
|
||||
Chips,
|
||||
FolderOpenIcon,
|
||||
Checkbox,
|
||||
formatProjectType,
|
||||
DropdownButton,
|
||||
EditIcon,
|
||||
GlobeIcon,
|
||||
HashIcon,
|
||||
Modal,
|
||||
XIcon,
|
||||
CheckCircleIcon,
|
||||
ShareIcon,
|
||||
DropdownIcon,
|
||||
GlobeIcon,
|
||||
FileIcon,
|
||||
EyeIcon,
|
||||
EyeOffIcon,
|
||||
ShareModal,
|
||||
CodeIcon,
|
||||
} from 'omorphia'
|
||||
import { computed, ref, watch } from 'vue'
|
||||
import { convertFileSrc } from '@tauri-apps/api/tauri'
|
||||
@@ -230,6 +344,7 @@ import { handleError } from '@/store/notifications.js'
|
||||
import mixpanel from 'mixpanel-browser'
|
||||
import { open } from '@tauri-apps/api/dialog'
|
||||
import { listen } from '@tauri-apps/api/event'
|
||||
import { MenuIcon, ToggleIcon, TextInputIcon, AddProjectImage } from '@/assets/icons'
|
||||
|
||||
const router = useRouter()
|
||||
|
||||
@@ -249,6 +364,8 @@ const props = defineProps({
|
||||
})
|
||||
|
||||
const projects = ref([])
|
||||
const selectionMap = ref(new Map())
|
||||
const showingOptions = ref(false)
|
||||
|
||||
const initProjects = (initInstance) => {
|
||||
projects.value = []
|
||||
@@ -295,22 +412,53 @@ const initProjects = (initInstance) => {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
const newSelectionMap = new Map()
|
||||
for (const project of projects.value) {
|
||||
newSelectionMap.set(
|
||||
project.path,
|
||||
selectionMap.value.get(project.path) ??
|
||||
selectionMap.value.get(project.path.slice(0, -9)) ??
|
||||
selectionMap.value.get(project.path + '.disabled') ??
|
||||
false
|
||||
)
|
||||
}
|
||||
selectionMap.value = newSelectionMap
|
||||
}
|
||||
|
||||
initProjects(props.instance)
|
||||
|
||||
watch(
|
||||
() => props.instance.projects,
|
||||
() => initProjects(props.instance)
|
||||
() => {
|
||||
initProjects(props.instance)
|
||||
}
|
||||
)
|
||||
|
||||
const searchFilter = ref('')
|
||||
const selectAll = ref(false)
|
||||
const sortFilter = ref('')
|
||||
const selectedProjectType = ref('All')
|
||||
const selected = computed(() => projects.value.filter((mod) => mod.selected))
|
||||
const deleteWarning = ref(null)
|
||||
const deleteDisabledWarning = ref(null)
|
||||
const hideNonSelected = ref(false)
|
||||
const selectedOption = ref('Share')
|
||||
const shareModal = ref(null)
|
||||
const ascending = ref(true)
|
||||
const sortColumn = ref('Name')
|
||||
|
||||
const selected = computed(() =>
|
||||
Array.from(selectionMap.value)
|
||||
.filter((args) => {
|
||||
return args[1]
|
||||
})
|
||||
.map((args) => {
|
||||
return projects.value.find((x) => x.path === args[0])
|
||||
})
|
||||
)
|
||||
|
||||
const functionValues = computed(() =>
|
||||
selected.value.length > 0 ? selected.value : Array.from(projects.value.values())
|
||||
)
|
||||
|
||||
const selectableProjectTypes = computed(() => {
|
||||
const obj = { All: 'all' }
|
||||
@@ -334,63 +482,71 @@ const search = computed(() => {
|
||||
})
|
||||
.filter((mod) => {
|
||||
if (hideNonSelected.value) {
|
||||
return mod.selected
|
||||
return !mod.disabled
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
return updateSort(filtered, sortFilter.value)
|
||||
return updateSort(filtered)
|
||||
})
|
||||
|
||||
function updateSort(projects, sort) {
|
||||
switch (sort) {
|
||||
const updateSort = (projects) => {
|
||||
switch (sortColumn.value) {
|
||||
case 'Version':
|
||||
return projects.slice().sort((a, b) => {
|
||||
if (a.version < b.version) {
|
||||
return -1
|
||||
return ascending.value ? -1 : 1
|
||||
}
|
||||
if (a.version > b.version) {
|
||||
return 1
|
||||
return ascending.value ? 1 : -1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
case 'Author':
|
||||
return projects.slice().sort((a, b) => {
|
||||
if (a.author < b.author) {
|
||||
return -1
|
||||
return ascending.value ? -1 : 1
|
||||
}
|
||||
if (a.author > b.author) {
|
||||
return 1
|
||||
return ascending.value ? 1 : -1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
case 'Enabled':
|
||||
return projects.slice().sort((a, b) => {
|
||||
if (a.disabled && !b.disabled) {
|
||||
return 1
|
||||
return ascending.value ? 1 : -1
|
||||
}
|
||||
if (!a.disabled && b.disabled) {
|
||||
return -1
|
||||
return ascending.value ? -1 : 1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
default:
|
||||
return projects.slice().sort((a, b) => {
|
||||
if (a.name < b.name) {
|
||||
return -1
|
||||
return ascending.value ? -1 : 1
|
||||
}
|
||||
if (a.name > b.name) {
|
||||
return 1
|
||||
return ascending.value ? 1 : -1
|
||||
}
|
||||
return 0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
async function updateAll(args) {
|
||||
if (args.option === 'update_all') {
|
||||
const sortProjects = (filter) => {
|
||||
if (sortColumn.value === filter) {
|
||||
ascending.value = !ascending.value
|
||||
} else {
|
||||
sortColumn.value = filter
|
||||
ascending.value = true
|
||||
}
|
||||
}
|
||||
|
||||
const updateAll = async () => {
|
||||
const setProjects = []
|
||||
for (const [i, project] of selected.value ?? projects.value.entries()) {
|
||||
for (const [i, project] of projects.value.entries()) {
|
||||
if (project.outdated) {
|
||||
project.updating = true
|
||||
setProjects.push(i)
|
||||
@@ -419,16 +575,17 @@ async function updateAll(args) {
|
||||
count: setProjects.length,
|
||||
selected: selected.value.length > 1,
|
||||
})
|
||||
} else {
|
||||
}
|
||||
|
||||
const selectUpdatable = () => {
|
||||
for (const project of projects.value) {
|
||||
if (project.outdated) {
|
||||
project.selected = true
|
||||
}
|
||||
selectionMap.value.set(project.path, true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function updateProject(mod) {
|
||||
const updateProject = async (mod) => {
|
||||
mod.updating = true
|
||||
mod.path = await update_project(props.instance.path, mod.path).catch(handleError)
|
||||
mod.updating = false
|
||||
@@ -446,7 +603,7 @@ async function updateProject(mod) {
|
||||
})
|
||||
}
|
||||
|
||||
async function toggleDisableMod(mod) {
|
||||
const toggleDisableMod = async (mod) => {
|
||||
mod.path = await toggle_disable_project(props.instance.path, mod.path).catch(handleError)
|
||||
mod.disabled = !mod.disabled
|
||||
mixpanel.track('InstanceProjectDisable', {
|
||||
@@ -459,7 +616,7 @@ async function toggleDisableMod(mod) {
|
||||
})
|
||||
}
|
||||
|
||||
async function removeMod(mod) {
|
||||
const removeMod = async (mod) => {
|
||||
await remove_project(props.instance.path, mod.path).catch(handleError)
|
||||
projects.value = projects.value.filter((x) => mod.path !== x.path)
|
||||
|
||||
@@ -472,6 +629,92 @@ async function removeMod(mod) {
|
||||
})
|
||||
}
|
||||
|
||||
const deleteSelected = async () => {
|
||||
for (const project of functionValues.value) {
|
||||
await remove_project(props.instance.path, project.path).catch(handleError)
|
||||
}
|
||||
|
||||
projects.value = projects.value.filter((x) => !x.selected)
|
||||
deleteWarning.value.hide()
|
||||
}
|
||||
|
||||
const deleteDisabled = async () => {
|
||||
for (const project of Array.of(projects.value.values().filter((x) => x.disabled))) {
|
||||
await remove_project(props.instance.path, project.path).catch(handleError)
|
||||
}
|
||||
|
||||
projects.value = projects.value.filter((x) => !x.selected)
|
||||
deleteDisabledWarning.value.hide()
|
||||
}
|
||||
|
||||
const shareNames = async () => {
|
||||
await shareModal.value.show(functionValues.value.map((x) => x.name).join('\n'))
|
||||
}
|
||||
|
||||
const shareFileNames = async () => {
|
||||
await shareModal.value.show(functionValues.value.map((x) => x.file_name).join('\n'))
|
||||
}
|
||||
|
||||
const shareUrls = async () => {
|
||||
await shareModal.value.show(
|
||||
functionValues.value
|
||||
.filter((x) => x.slug)
|
||||
.map((x) => `https://modrinth.com/${x.project_type}/${x.slug}`)
|
||||
.join('\n')
|
||||
)
|
||||
}
|
||||
|
||||
const shareMarkdown = async () => {
|
||||
await shareModal.value.show(
|
||||
functionValues.value
|
||||
.map((x) => {
|
||||
if (x.slug) {
|
||||
return `[${x.name}](https://modrinth.com/${x.project_type}/${x.slug})`
|
||||
}
|
||||
return x.name
|
||||
})
|
||||
.join('\n')
|
||||
)
|
||||
}
|
||||
|
||||
const toggleSelected = async () => {
|
||||
for (const project of functionValues.value) {
|
||||
await toggleDisableMod(project, !project.disabled)
|
||||
}
|
||||
}
|
||||
|
||||
const enableAll = async () => {
|
||||
for (const project of functionValues.value) {
|
||||
if (project.disabled) {
|
||||
await toggleDisableMod(project, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const disableAll = async () => {
|
||||
for (const project of functionValues.value) {
|
||||
if (!project.disabled) {
|
||||
await toggleDisableMod(project, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const hideShowAll = async () => {
|
||||
hideNonSelected.value = !hideNonSelected.value
|
||||
}
|
||||
|
||||
const handleRightClick = (event, mod) => {
|
||||
if (mod.slug && mod.project_type) {
|
||||
props.options.showMenu(
|
||||
event,
|
||||
{
|
||||
link: `https://modrinth.com/${mod.project_type}/${mod.slug}`,
|
||||
},
|
||||
[{ name: 'open_link' }, { name: 'copy_link' }]
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const handleContentOptionClick = async (args) => {
|
||||
if (args.option === 'search') {
|
||||
await router.push({
|
||||
@@ -484,94 +727,25 @@ const handleContentOptionClick = async (args) => {
|
||||
|
||||
for (const project of newProject) {
|
||||
await add_project_from_path(props.instance.path, project, 'mod').catch(handleError)
|
||||
}
|
||||
initProjects(await get(props.instance.path).catch(handleError))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listen('tauri://file-drop', async (event) => {
|
||||
for (const file of event.payload) {
|
||||
await add_project_from_path(props.instance.path, file, 'mod').catch(handleError)
|
||||
initProjects(await get(props.instance.path).catch(handleError))
|
||||
}
|
||||
})
|
||||
|
||||
async function deleteSelected() {
|
||||
for (const project of selected.value) {
|
||||
await remove_project(props.instance.path, project.path).catch(handleError)
|
||||
}
|
||||
projects.value = projects.value.filter((x) => !x.selected)
|
||||
deleteWarning.value.hide()
|
||||
}
|
||||
|
||||
async function copySelected(args) {
|
||||
switch (args.option) {
|
||||
case 'copy_name':
|
||||
await navigator.clipboard.writeText(selected.value.map((x) => x.name).join('\n'))
|
||||
break
|
||||
case 'copy_slug':
|
||||
await navigator.clipboard.writeText(
|
||||
selected.value
|
||||
.filter((x) => x.slug)
|
||||
.map((x) => x.slug)
|
||||
.join('\n')
|
||||
)
|
||||
break
|
||||
case 'copy_url':
|
||||
await navigator.clipboard.writeText(
|
||||
selected.value
|
||||
.filter((x) => x.slug)
|
||||
.map((x) => `https://modrinth.com/${x.project_type}/${x.slug}`)
|
||||
.join('\n')
|
||||
)
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
async function toggleSelected(args) {
|
||||
switch (args.option) {
|
||||
case 'toggle':
|
||||
for (const project of selected.value) {
|
||||
await toggleDisableMod(project)
|
||||
}
|
||||
break
|
||||
case 'enable':
|
||||
for (const project of selected.value) {
|
||||
if (project.disabled) {
|
||||
await toggleDisableMod(project)
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'disable':
|
||||
for (const project of selected.value) {
|
||||
if (!project.disabled) {
|
||||
await toggleDisableMod(project)
|
||||
}
|
||||
}
|
||||
break
|
||||
case 'hide_show':
|
||||
hideNonSelected.value = !hideNonSelected.value
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
watch(selectAll, () => {
|
||||
for (const project of projects.value) {
|
||||
project.selected = selectAll.value
|
||||
for (const [key, value] of Array.from(selectionMap.value)) {
|
||||
if (value !== selectAll.value) {
|
||||
selectionMap.value.set(key, selectAll.value)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const handleRightClick = (event, mod) => {
|
||||
if (mod.slug && mod.project_type) {
|
||||
props.options.showMenu(
|
||||
event,
|
||||
{
|
||||
link: `https://modrinth.com/${mod.project_type}/${mod.slug}`,
|
||||
},
|
||||
[{ name: 'open_link' }, { name: 'copy_link' }]
|
||||
)
|
||||
listen('tauri://file-drop', async (event) => {
|
||||
for (const file of event.payload) {
|
||||
await add_project_from_path(props.instance.path, file, 'mod').catch(handleError)
|
||||
}
|
||||
}
|
||||
initProjects(await get(props.instance.path).catch(handleError))
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@@ -586,10 +760,23 @@ const handleRightClick = (event, mod) => {
|
||||
|
||||
.table {
|
||||
margin-block-start: 0;
|
||||
border-radius: var(--radius-lg);
|
||||
border: 2px solid var(--color-bg);
|
||||
}
|
||||
|
||||
.table-row {
|
||||
grid-template-columns: min-content 2fr 1fr 1fr 11rem;
|
||||
|
||||
&.show-options {
|
||||
grid-template-columns: min-content auto;
|
||||
|
||||
.options {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
gap: var(--gap-md);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.table-cell {
|
||||
@@ -599,6 +786,7 @@ const handleRightClick = (event, mod) => {
|
||||
.card-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: var(--gap-md);
|
||||
justify-content: space-between;
|
||||
background-color: var(--color-raised-bg);
|
||||
}
|
||||
@@ -606,7 +794,8 @@ const handleRightClick = (event, mod) => {
|
||||
.mod-card {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 1rem;
|
||||
gap: var(--gap-sm);
|
||||
justify-content: center;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
@@ -655,6 +844,91 @@ const handleRightClick = (event, mod) => {
|
||||
color: var(--color-contrast);
|
||||
}
|
||||
}
|
||||
|
||||
.actions-cell {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 0.5rem;
|
||||
|
||||
.btn {
|
||||
height: unset;
|
||||
width: unset;
|
||||
padding: 0;
|
||||
|
||||
&.trash {
|
||||
color: var(--color-red);
|
||||
}
|
||||
|
||||
&.update {
|
||||
color: var(--color-green);
|
||||
}
|
||||
|
||||
&.share {
|
||||
color: var(--color-blue);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.more-box {
|
||||
display: flex;
|
||||
background-color: var(--color-bg);
|
||||
padding: var(--gap-lg);
|
||||
|
||||
.options {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: row;
|
||||
gap: var(--gap-md);
|
||||
flex-grow: 1;
|
||||
}
|
||||
}
|
||||
|
||||
.btn {
|
||||
&.transparent {
|
||||
height: unset;
|
||||
width: unset;
|
||||
padding: 0;
|
||||
color: var(--color-base);
|
||||
gap: var(--gap-xs);
|
||||
white-space: nowrap;
|
||||
|
||||
svg {
|
||||
margin-right: 0 !important;
|
||||
transition: transform 0.2s ease-in-out;
|
||||
|
||||
&.open {
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
|
||||
&.down {
|
||||
transform: rotate(180deg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.empty-prompt {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
gap: var(--gap-md);
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
|
||||
.empty-icon {
|
||||
svg {
|
||||
width: 10rem;
|
||||
height: 10rem;
|
||||
color: var(--color-contrast);
|
||||
}
|
||||
}
|
||||
|
||||
p,
|
||||
h3 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.updating-indicator {
|
||||
|
||||