Create form for adding aliases
This commit is contained in:
parent
12df3fe955
commit
2d164cdd19
5 changed files with 119 additions and 10 deletions
|
@ -9,6 +9,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
|
|||
### Added
|
||||
|
||||
- Added "Aliases" page.
|
||||
- Form for adding aliases.
|
||||
|
||||
## [1.19.0] - 2023-03-30
|
||||
|
||||
|
|
|
@ -29,12 +29,16 @@ export async function getSearchResults(
|
|||
}
|
||||
|
||||
export async function searchProfilesByAcct(
|
||||
authToken: string | null,
|
||||
acct: string,
|
||||
resolve: boolean = false,
|
||||
limit = 40,
|
||||
): Promise<Profile[]> {
|
||||
const url = `${BACKEND_URL}/api/v1/accounts/search`
|
||||
const response = await http(url, {
|
||||
method: "GET",
|
||||
queryParams: { q: acct },
|
||||
queryParams: { q: acct, resolve, limit },
|
||||
authToken,
|
||||
})
|
||||
const data = await response.json()
|
||||
if (response.status !== 200) {
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { BACKEND_URL } from "@/constants"
|
||||
import { http } from "./common"
|
||||
import { User } from "./users"
|
||||
import { Aliases, User } from "./users"
|
||||
|
||||
export async function changePassword(
|
||||
authToken: string,
|
||||
|
@ -20,6 +20,24 @@ export async function changePassword(
|
|||
}
|
||||
}
|
||||
|
||||
export async function addAlias(
|
||||
authToken: string,
|
||||
acct: string,
|
||||
): Promise<Aliases> {
|
||||
const url = `${BACKEND_URL}/api/v1/settings/aliases`
|
||||
const response = await http(url, {
|
||||
method: "POST",
|
||||
json: { acct: acct },
|
||||
authToken,
|
||||
})
|
||||
const data = await response.json()
|
||||
if (response.status !== 200) {
|
||||
throw new Error(data.error_description)
|
||||
} else {
|
||||
return data
|
||||
}
|
||||
}
|
||||
|
||||
async function downloadBlob(blob: Blob, name: string) {
|
||||
const fileUrl = window.URL.createObjectURL(blob)
|
||||
const hiddenLink = document.createElement("a")
|
||||
|
|
|
@ -194,7 +194,7 @@ async function identifySender() {
|
|||
return
|
||||
}
|
||||
isLoading = true
|
||||
const profiles = await searchProfilesByAcct(senderAcct)
|
||||
const profiles = await searchProfilesByAcct(null, senderAcct)
|
||||
if (profiles.length > 1) {
|
||||
senderError = "Please provide full address"
|
||||
} else {
|
||||
|
|
|
@ -22,9 +22,40 @@
|
|||
<profile-list-item :profile="profile"></profile-list-item>
|
||||
</router-link>
|
||||
</section>
|
||||
<div class="not-found" v-if="isEmpty() && !isLoading">
|
||||
No aliases found
|
||||
</div>
|
||||
<section>
|
||||
<h2>Add alias</h2>
|
||||
<form @submit.prevent="onAddAlias()">
|
||||
<div class="input-group">
|
||||
<input
|
||||
id="alias"
|
||||
type="text"
|
||||
v-model="newAlias"
|
||||
placeholder="Fediverse address"
|
||||
@input="newAliasSuggestions = []; newAliasError = null"
|
||||
>
|
||||
<div class="suggestions" v-if="newAliasSuggestions.length > 0">
|
||||
<button
|
||||
class="suggestion"
|
||||
v-for="profile in newAliasSuggestions"
|
||||
:key="profile.id"
|
||||
@click="newAlias = profile.acct; newAliasSuggestions = []"
|
||||
>
|
||||
{{ profile.acct }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
type="submit"
|
||||
class="btn"
|
||||
:disabled="!canAddAlias()"
|
||||
>
|
||||
Add
|
||||
</button>
|
||||
<div class="error-message" v-if="newAliasError">
|
||||
{{ newAliasError }}
|
||||
</div>
|
||||
</form>
|
||||
</section>
|
||||
<loader v-if="isLoading"></loader>
|
||||
</template>
|
||||
</sidebar-layout>
|
||||
|
@ -34,16 +65,21 @@
|
|||
import { onMounted } from "vue"
|
||||
import { $, $ref } from "vue/macros"
|
||||
|
||||
import { getAliases, Aliases } from "@/api/users"
|
||||
import { searchProfilesByAcct } from "@/api/search"
|
||||
import { addAlias } from "@/api/settings"
|
||||
import { getAliases, Aliases, Profile } from "@/api/users"
|
||||
import SidebarLayout from "@/components/SidebarLayout.vue"
|
||||
import Loader from "@/components/Loader.vue"
|
||||
import ProfileListItem from "@/components/ProfileListItem.vue"
|
||||
import { useCurrentUser } from "@/store/user"
|
||||
|
||||
const { ensureCurrentUser } = $(useCurrentUser())
|
||||
const { ensureCurrentUser, ensureAuthToken } = $(useCurrentUser())
|
||||
|
||||
let aliases = $ref<Aliases>({ declared: [], verified: [] })
|
||||
let isLoading = $ref(false)
|
||||
let newAlias = $ref<string>("")
|
||||
let newAliasSuggestions = $ref<Profile[]>([])
|
||||
let newAliasError = $ref<string | null>(null)
|
||||
|
||||
onMounted(async () => {
|
||||
isLoading = true
|
||||
|
@ -51,13 +87,37 @@ onMounted(async () => {
|
|||
isLoading = false
|
||||
})
|
||||
|
||||
function isEmpty(): boolean {
|
||||
return aliases.declared.length === 0 && aliases.verified.length === 0
|
||||
function canAddAlias(): boolean {
|
||||
return newAlias.length > 0 && newAliasError === null
|
||||
}
|
||||
|
||||
async function onAddAlias() {
|
||||
isLoading = true
|
||||
const profiles = await searchProfilesByAcct(
|
||||
ensureAuthToken(),
|
||||
newAlias,
|
||||
true,
|
||||
5,
|
||||
)
|
||||
if (profiles.length === 0) {
|
||||
newAliasError = "Profile not found"
|
||||
isLoading = false
|
||||
return
|
||||
}
|
||||
if (profiles.length === 1 && profiles[0].acct === newAlias) {
|
||||
aliases = await addAlias(ensureAuthToken(), newAlias)
|
||||
newAlias = ""
|
||||
} else {
|
||||
newAliasSuggestions = profiles
|
||||
}
|
||||
isLoading = false
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import "../styles/layout";
|
||||
@import "../styles/mixins";
|
||||
@import "../styles/theme";
|
||||
|
||||
section {
|
||||
margin-bottom: $block-outer-padding;
|
||||
|
@ -67,6 +127,32 @@ section {
|
|||
margin-bottom: $block-outer-padding;
|
||||
}
|
||||
|
||||
form {
|
||||
@include content-form;
|
||||
|
||||
.suggestions {
|
||||
background-color: var(--block-background-color);
|
||||
border-radius: $btn-border-radius;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
margin-top: 1px;
|
||||
|
||||
.suggestion {
|
||||
padding: calc($input-padding / 2) $input-padding;
|
||||
text-align: left;
|
||||
word-wrap: break-word;
|
||||
|
||||
&:first-child {
|
||||
padding-top: $input-padding;
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
padding-bottom: $input-padding;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.loader {
|
||||
margin: $block-outer-padding auto;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue