working acceptance + download
This commit is contained in:
parent
719aded698
commit
1018d05e36
@ -46,6 +46,30 @@ pub struct SharedProfileOverrideHashes {
|
|||||||
pub sha512: String,
|
pub sha512: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Simplified version of SharedProfile- this is what is returned from the Labrinth API
|
||||||
|
// This is not used, except for requests where we are not a member of the shared profile
|
||||||
|
// (ie: previewing a shared profile from a link, before accepting it)
|
||||||
|
#[derive(Deserialize, Serialize, Debug)]
|
||||||
|
pub struct SharedProfileResponse {
|
||||||
|
pub id: String,
|
||||||
|
pub name: String,
|
||||||
|
pub owner_id: String,
|
||||||
|
pub created: DateTime<Utc>,
|
||||||
|
pub updated: DateTime<Utc>,
|
||||||
|
pub icon_url: Option<String>,
|
||||||
|
|
||||||
|
pub loader: ModLoader,
|
||||||
|
pub game : String,
|
||||||
|
|
||||||
|
pub loader_version: String,
|
||||||
|
pub game_version: String,
|
||||||
|
|
||||||
|
// Present only if we are the owner
|
||||||
|
pub share_links: Option<Vec<SharedProfileLink>>,
|
||||||
|
pub users: Option<Vec<String>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Create a new shared profile from ProfilePathId
|
// Create a new shared profile from ProfilePathId
|
||||||
// This converts the LinkedData to a SharedProfile and uploads it to the Labrinth API
|
// This converts the LinkedData to a SharedProfile and uploads it to the Labrinth API
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
@ -177,27 +201,6 @@ pub async fn get_all() -> crate::Result<Vec<SharedProfile>> {
|
|||||||
let creds = state.credentials.read().await;
|
let creds = state.credentials.read().await;
|
||||||
let creds = creds.0.as_ref().ok_or_else(|| crate::ErrorKind::NoCredentialsError)?;
|
let creds = creds.0.as_ref().ok_or_else(|| crate::ErrorKind::NoCredentialsError)?;
|
||||||
|
|
||||||
// First, get list of shared profiles the user has access to
|
|
||||||
#[derive(Deserialize, Serialize, Debug)]
|
|
||||||
pub struct SharedProfileResponse {
|
|
||||||
pub id: String,
|
|
||||||
pub name: String,
|
|
||||||
pub owner_id: String,
|
|
||||||
pub created: DateTime<Utc>,
|
|
||||||
pub updated: DateTime<Utc>,
|
|
||||||
pub icon_url: Option<String>,
|
|
||||||
|
|
||||||
pub loader: ModLoader,
|
|
||||||
pub game : String,
|
|
||||||
|
|
||||||
pub loader_version: String,
|
|
||||||
pub game_version: String,
|
|
||||||
|
|
||||||
// Present only if we are the owner
|
|
||||||
pub share_links: Option<Vec<SharedProfileLink>>,
|
|
||||||
pub users: Option<Vec<String>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
let response = REQWEST_CLIENT
|
let response = REQWEST_CLIENT
|
||||||
.get(
|
.get(
|
||||||
format!("{MODRINTH_API_URL_INTERNAL}client/user"),
|
format!("{MODRINTH_API_URL_INTERNAL}client/user"),
|
||||||
@ -205,6 +208,7 @@ pub async fn get_all() -> crate::Result<Vec<SharedProfile>> {
|
|||||||
.header("Authorization", &creds.session)
|
.header("Authorization", &creds.session)
|
||||||
.send().await?.error_for_status()?;
|
.send().await?.error_for_status()?;
|
||||||
|
|
||||||
|
// First, get list of shared profiles the user has access to
|
||||||
let profiles = response.json::<Vec<SharedProfileResponse>>().await?;
|
let profiles = response.json::<Vec<SharedProfileResponse>>().await?;
|
||||||
|
|
||||||
// Next, get files for each shared profile
|
// Next, get files for each shared profile
|
||||||
@ -253,8 +257,9 @@ pub async fn get_all() -> crate::Result<Vec<SharedProfile>> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument]
|
#[tracing::instrument]
|
||||||
pub async fn install(shared_profile : SharedProfile) -> crate::Result<ProfilePathId> {
|
pub async fn install(shared_profile_id : String) -> crate::Result<ProfilePathId> {
|
||||||
let state = crate::State::get().await?;
|
let state = crate::State::get().await?;
|
||||||
|
let shared_profile = get_all().await?.into_iter().find(|x| x.id == shared_profile_id).ok_or_else(|| crate::ErrorKind::OtherError("Profile not found".to_string()))?;
|
||||||
|
|
||||||
let linked_data = LinkedData::SharedProfile {
|
let linked_data = LinkedData::SharedProfile {
|
||||||
profile_id: shared_profile.id,
|
profile_id: shared_profile.id,
|
||||||
@ -647,10 +652,32 @@ pub async fn accept_share_link(
|
|||||||
|
|
||||||
REQWEST_CLIENT
|
REQWEST_CLIENT
|
||||||
.post(
|
.post(
|
||||||
format!("{MODRINTH_API_URL_INTERNAL}client/profile/share/{link}/accept"),
|
format!("{MODRINTH_API_URL_INTERNAL}client/share/{link}/accept"),
|
||||||
)
|
)
|
||||||
.header("Authorization", &creds.session)
|
.header("Authorization", &creds.session)
|
||||||
.send().await?.error_for_status()?;
|
.send().await?.error_for_status()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets a shared profile from a share link
|
||||||
|
// This is done without accepting it- so would not include any link information, and is only usable for basic info
|
||||||
|
pub async fn get_from_link(
|
||||||
|
link: String
|
||||||
|
) -> crate::Result<SharedProfileResponse> {
|
||||||
|
let state = crate::State::get().await?;
|
||||||
|
|
||||||
|
let creds = state.credentials.read().await;
|
||||||
|
let creds = creds.0.as_ref().ok_or_else(|| crate::ErrorKind::NoCredentialsError)?;
|
||||||
|
|
||||||
|
let response = REQWEST_CLIENT
|
||||||
|
.get(
|
||||||
|
format!("{MODRINTH_API_URL_INTERNAL}client/share/{link}"),
|
||||||
|
)
|
||||||
|
.header("Authorization", &creds.session)
|
||||||
|
.send().await?.error_for_status()?;
|
||||||
|
|
||||||
|
let profile = response.json::<SharedProfileResponse>().await?;
|
||||||
|
|
||||||
|
Ok(profile)
|
||||||
}
|
}
|
||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::api::Result;
|
use crate::api::Result;
|
||||||
use theseus::{prelude::*, shared_profile::SharedProfile};
|
use theseus::{prelude::*, shared_profile::{SharedProfile,SharedProfileResponse}};
|
||||||
|
|
||||||
pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
|
pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
|
||||||
tauri::plugin::Builder::new("profile_share")
|
tauri::plugin::Builder::new("profile_share")
|
||||||
@ -12,7 +12,8 @@ pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
|
|||||||
profile_share_generate_share_link,
|
profile_share_generate_share_link,
|
||||||
profile_share_accept_share_link,
|
profile_share_accept_share_link,
|
||||||
profile_share_remove_users,
|
profile_share_remove_users,
|
||||||
profile_share_remove_links
|
profile_share_remove_links,
|
||||||
|
profile_share_get_link_id,
|
||||||
])
|
])
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
@ -28,9 +29,9 @@ pub async fn profile_share_get_all(
|
|||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn profile_share_install(
|
pub async fn profile_share_install(
|
||||||
profile: SharedProfile,
|
shared_profile_id: String,
|
||||||
) -> Result<ProfilePathId> {
|
) -> Result<ProfilePathId> {
|
||||||
let res = shared_profile::install(profile)
|
let res = shared_profile::install(shared_profile_id)
|
||||||
.await?;
|
.await?;
|
||||||
Ok(res)
|
Ok(res)
|
||||||
}
|
}
|
||||||
@ -77,6 +78,17 @@ pub async fn profile_share_accept_share_link(
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Gets a shared profile from a share link
|
||||||
|
// This is done without accepting it- so would not include any link information, and is only usable for basic info
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn profile_share_get_link_id(
|
||||||
|
link : String
|
||||||
|
) -> Result<SharedProfileResponse> {
|
||||||
|
let res = shared_profile::get_from_link(link).await?;
|
||||||
|
Ok(res)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn profile_share_remove_users(
|
pub async fn profile_share_remove_users(
|
||||||
path : ProfilePathId,
|
path : ProfilePathId,
|
||||||
|
|||||||
@ -20,7 +20,8 @@ pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
|
|||||||
get_opening_command,
|
get_opening_command,
|
||||||
await_sync,
|
await_sync,
|
||||||
is_offline,
|
is_offline,
|
||||||
refresh_offline
|
refresh_offline,
|
||||||
|
test_command,
|
||||||
])
|
])
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
@ -159,6 +160,11 @@ pub async fn get_opening_command() -> Result<Option<CommandPayload>> {
|
|||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[tauri::command]
|
||||||
|
pub async fn test_command(command: String) -> Result<()> {
|
||||||
|
Ok(handle_command(command).await?)
|
||||||
|
}
|
||||||
|
|
||||||
// helper function called when redirected by a weblink (ie: modrith://do-something) or when redirected by a .mrpack file (in which case its a filepath)
|
// helper function called when redirected by a weblink (ie: modrith://do-something) or when redirected by a .mrpack file (in which case its a filepath)
|
||||||
// We hijack the deep link library (which also contains functionality for instance-checking)
|
// We hijack the deep link library (which also contains functionality for instance-checking)
|
||||||
pub async fn handle_command(command: String) -> Result<()> {
|
pub async fn handle_command(command: String) -> Result<()> {
|
||||||
|
|||||||
@ -1,10 +1,8 @@
|
|||||||
<script setup>
|
<script setup>
|
||||||
import { Modal, Button } from 'omorphia'
|
import { Modal, Button } from 'omorphia'
|
||||||
import { ref } from 'vue'
|
import { ref } from 'vue'
|
||||||
import { useFetch } from '@/helpers/fetch.js'
|
|
||||||
import SearchCard from '@/components/ui/SearchCard.vue'
|
|
||||||
import { handleError } from '@/store/notifications.js'
|
import { handleError } from '@/store/notifications.js'
|
||||||
import { share_accept, share_install } from '@/helpers/shared_profiles.js'
|
import { share_accept, share_install, share_get_link_id } from '@/helpers/shared_profiles.js'
|
||||||
|
|
||||||
const confirmModal = ref(null)
|
const confirmModal = ref(null)
|
||||||
const linkId = ref(null)
|
const linkId = ref(null)
|
||||||
@ -12,13 +10,11 @@ const sharedProfile = ref(null)
|
|||||||
|
|
||||||
defineExpose({
|
defineExpose({
|
||||||
async show(event) {
|
async show(event) {
|
||||||
linkId.value = event.id
|
console.log('showing accept shared profile modal', event)
|
||||||
sharedProfile.value = await useFetch(
|
linkId.value = event.link
|
||||||
`https://staging-api.modrinth.com/_internal/share/${encodeURIComponent(event.id)}`,
|
sharedProfile.value = await share_get_link_id(linkId.value).catch(handleError)
|
||||||
'shared profile'
|
|
||||||
)
|
|
||||||
|
|
||||||
confirmModal.value.show()
|
confirmModal.value.show()
|
||||||
|
console.log('sharedProfile')
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -30,18 +26,12 @@ async function install() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Modal ref="confirmModal" :header="`Install ${project?.title}`">
|
<Modal ref="confirmModal" :header="`Install ${sharedProfile?.name}`">
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<SearchCard
|
|
||||||
:project="project"
|
|
||||||
class="project-card"
|
|
||||||
:categories="categories"
|
|
||||||
@open="confirmModal.hide()"
|
|
||||||
/>
|
|
||||||
<div class="button-row">
|
<div class="button-row">
|
||||||
<div class="markdown-body">
|
<div class="markdown-body">
|
||||||
<p>
|
<p>
|
||||||
Installing <code>{{ sharedProfile.id }}</code> from user {{ sharedProfile.owner_id }}
|
Installing <code>{{ sharedProfile.name }}</code> from user {{ sharedProfile.owner_id }}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="button-group">
|
<div class="button-group">
|
||||||
|
|||||||
@ -15,9 +15,15 @@ export async function share_generate(path) {
|
|||||||
return await invoke('plugin:profile_share|profile_share_generate_share_link', { path })
|
return await invoke('plugin:profile_share|profile_share_generate_share_link', { path })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Gets the shared profile from the link id
|
||||||
|
// This is done without accepting it- so would not include any link information, and is only usable for basic info
|
||||||
|
export async function share_get_link_id(link) {
|
||||||
|
return await invoke('plugin:profile_share|profile_share_get_link_id', { link })
|
||||||
|
}
|
||||||
|
|
||||||
/// Accepts a shared profile link
|
/// Accepts a shared profile link
|
||||||
export async function share_accept(link) {
|
export async function share_accept(link) {
|
||||||
return await invoke('plugin:profile_share|profile_share_accept', { link })
|
return await invoke('plugin:profile_share|profile_share_accept_share_link', { link })
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Removes users from a shared profile
|
/// Removes users from a shared profile
|
||||||
@ -31,8 +37,8 @@ export async function remove_links(path, links) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Install a pack from a shared profile id
|
/// Install a pack from a shared profile id
|
||||||
export async function share_install(id) {
|
export async function share_install(sharedProfileId) {
|
||||||
return await invoke('plugin:profile_share|profile_share_install', { id })
|
return await invoke('plugin:profile_share|profile_share_install', { sharedProfileId })
|
||||||
}
|
}
|
||||||
|
|
||||||
// get all user profiles that are available to the currentt user
|
// get all user profiles that are available to the currentt user
|
||||||
|
|||||||
@ -29,10 +29,15 @@ const raw_invoke = async (plugin, fn, args) => {
|
|||||||
return await invoke('plugin:' + plugin + '|' + fn, args)
|
return await invoke('plugin:' + plugin + '|' + fn, args)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
const test_command = async (command) => {
|
||||||
|
return await raw_invoke('utils', 'test_command', {command })
|
||||||
|
}
|
||||||
|
|
||||||
isDev()
|
isDev()
|
||||||
.then((dev) => {
|
.then((dev) => {
|
||||||
if (dev) {
|
if (dev) {
|
||||||
window.raw_invoke = raw_invoke
|
window.raw_invoke = raw_invoke
|
||||||
|
window.test_command = test_command
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
|
|||||||
@ -492,9 +492,6 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="installedSharedProfileData.is_owned" class="adjacent-input">
|
<div v-if="installedSharedProfileData.is_owned" class="adjacent-input">
|
||||||
your project
|
|
||||||
{{ props.instance.sync_update_version }}
|
|
||||||
:)
|
|
||||||
<label for="share-sync">
|
<label for="share-sync">
|
||||||
<span class="label__title">Sync shared profile</span>
|
<span class="label__title">Sync shared profile</span>
|
||||||
<span class="label__description" v-if="props.instance.sync_update_version?.is_synced">
|
<span class="label__description" v-if="props.instance.sync_update_version?.is_synced">
|
||||||
@ -511,9 +508,7 @@
|
|||||||
<GlobeIcon /> Revert
|
<GlobeIcon /> Revert
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
<div v-else>
|
<div v-else class="adjacent-input">
|
||||||
not yours
|
|
||||||
{{ props.instance.sync_update_version }}
|
|
||||||
<label for="share-sync">
|
<label for="share-sync">
|
||||||
<span class="label__title">Sync shared profile</span>
|
<span class="label__title">Sync shared profile</span>
|
||||||
<span class="label__description" v-if="props.instance.sync_update_version?.is_synced">
|
<span class="label__description" v-if="props.instance.sync_update_version?.is_synced">
|
||||||
@ -523,10 +518,11 @@
|
|||||||
You are not up to date with the shared profile. Click the button to update your instance.
|
You are not up to date with the shared profile. Click the button to update your instance.
|
||||||
</span>
|
</span>
|
||||||
</label>
|
</label>
|
||||||
<Button id="share-sync-sync" @click="inboundSyncSharedProfile">
|
<Button id="share-sync-sync" @click="inboundSyncSharedProfile" :disabled="props.instance.sync_update_version?.is_synced">
|
||||||
<GlobeIcon /> Sync
|
<GlobeIcon /> Sync
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
|
{{ props.instance.sync_update_version }}
|
||||||
</Card>
|
</Card>
|
||||||
<Card>
|
<Card>
|
||||||
<div class="label">
|
<div class="label">
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user