working acceptance + download

This commit is contained in:
thesuzerain 2024-01-30 19:14:47 -08:00
parent 719aded698
commit 1018d05e36
7 changed files with 97 additions and 55 deletions

View File

@ -46,6 +46,30 @@ pub struct SharedProfileOverrideHashes {
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
// This converts the LinkedData to a SharedProfile and uploads it to the Labrinth API
#[tracing::instrument]
@ -177,27 +201,6 @@ pub async fn get_all() -> crate::Result<Vec<SharedProfile>> {
let creds = state.credentials.read().await;
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
.get(
format!("{MODRINTH_API_URL_INTERNAL}client/user"),
@ -205,6 +208,7 @@ pub async fn get_all() -> crate::Result<Vec<SharedProfile>> {
.header("Authorization", &creds.session)
.send().await?.error_for_status()?;
// First, get list of shared profiles the user has access to
let profiles = response.json::<Vec<SharedProfileResponse>>().await?;
// Next, get files for each shared profile
@ -253,8 +257,9 @@ pub async fn get_all() -> crate::Result<Vec<SharedProfile>> {
}
#[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 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 {
profile_id: shared_profile.id,
@ -647,10 +652,32 @@ pub async fn accept_share_link(
REQWEST_CLIENT
.post(
format!("{MODRINTH_API_URL_INTERNAL}client/profile/share/{link}/accept"),
format!("{MODRINTH_API_URL_INTERNAL}client/share/{link}/accept"),
)
.header("Authorization", &creds.session)
.send().await?.error_for_status()?;
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)
}

View File

@ -1,5 +1,5 @@
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> {
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_accept_share_link,
profile_share_remove_users,
profile_share_remove_links
profile_share_remove_links,
profile_share_get_link_id,
])
.build()
}
@ -28,9 +29,9 @@ pub async fn profile_share_get_all(
#[tauri::command]
pub async fn profile_share_install(
profile: SharedProfile,
shared_profile_id: String,
) -> Result<ProfilePathId> {
let res = shared_profile::install(profile)
let res = shared_profile::install(shared_profile_id)
.await?;
Ok(res)
}
@ -77,6 +78,17 @@ pub async fn profile_share_accept_share_link(
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]
pub async fn profile_share_remove_users(
path : ProfilePathId,

View File

@ -20,7 +20,8 @@ pub fn init<R: tauri::Runtime>() -> tauri::plugin::TauriPlugin<R> {
get_opening_command,
await_sync,
is_offline,
refresh_offline
refresh_offline,
test_command,
])
.build()
}
@ -159,6 +160,11 @@ pub async fn get_opening_command() -> Result<Option<CommandPayload>> {
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)
// We hijack the deep link library (which also contains functionality for instance-checking)
pub async fn handle_command(command: String) -> Result<()> {

View File

@ -1,10 +1,8 @@
<script setup>
import { Modal, Button } from 'omorphia'
import { ref } from 'vue'
import { useFetch } from '@/helpers/fetch.js'
import SearchCard from '@/components/ui/SearchCard.vue'
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 linkId = ref(null)
@ -12,13 +10,11 @@ const sharedProfile = ref(null)
defineExpose({
async show(event) {
linkId.value = event.id
sharedProfile.value = await useFetch(
`https://staging-api.modrinth.com/_internal/share/${encodeURIComponent(event.id)}`,
'shared profile'
)
console.log('showing accept shared profile modal', event)
linkId.value = event.link
sharedProfile.value = await share_get_link_id(linkId.value).catch(handleError)
confirmModal.value.show()
console.log('sharedProfile')
},
})
@ -30,18 +26,12 @@ async function install() {
</script>
<template>
<Modal ref="confirmModal" :header="`Install ${project?.title}`">
<Modal ref="confirmModal" :header="`Install ${sharedProfile?.name}`">
<div class="modal-body">
<SearchCard
:project="project"
class="project-card"
:categories="categories"
@open="confirmModal.hide()"
/>
<div class="button-row">
<div class="markdown-body">
<p>
Installing <code>{{ sharedProfile.id }}</code> from user {{ sharedProfile.owner_id }}
Installing <code>{{ sharedProfile.name }}</code> from user {{ sharedProfile.owner_id }}
</p>
</div>
<div class="button-group">

View File

@ -15,9 +15,15 @@ export async function share_generate(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
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
@ -31,8 +37,8 @@ export async function remove_links(path, links) {
}
/// Install a pack from a shared profile id
export async function share_install(id) {
return await invoke('plugin:profile_share|profile_share_install', { id })
export async function share_install(sharedProfileId) {
return await invoke('plugin:profile_share|profile_share_install', { sharedProfileId })
}
// get all user profiles that are available to the currentt user

View File

@ -29,10 +29,15 @@ const raw_invoke = async (plugin, fn, args) => {
return await invoke('plugin:' + plugin + '|' + fn, args)
}
}
const test_command = async (command) => {
return await raw_invoke('utils', 'test_command', {command })
}
isDev()
.then((dev) => {
if (dev) {
window.raw_invoke = raw_invoke
window.test_command = test_command
}
})
.catch((err) => {

View File

@ -492,9 +492,6 @@
</div>
</div>
<div v-if="installedSharedProfileData.is_owned" class="adjacent-input">
your project
{{ props.instance.sync_update_version }}
:)
<label for="share-sync">
<span class="label__title">Sync shared profile</span>
<span class="label__description" v-if="props.instance.sync_update_version?.is_synced">
@ -511,9 +508,7 @@
<GlobeIcon /> Revert
</Button>
</div>
<div v-else>
not yours
{{ props.instance.sync_update_version }}
<div v-else class="adjacent-input">
<label for="share-sync">
<span class="label__title">Sync shared profile</span>
<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.
</span>
</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
</Button>
</div>
{{ props.instance.sync_update_version }}
</Card>
<Card>
<div class="label">