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
|
||||||
|
|
||||||
- Added "Aliases" page.
|
- Added "Aliases" page.
|
||||||
|
- Form for adding aliases.
|
||||||
|
|
||||||
## [1.19.0] - 2023-03-30
|
## [1.19.0] - 2023-03-30
|
||||||
|
|
||||||
|
|
|
@ -29,12 +29,16 @@ export async function getSearchResults(
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function searchProfilesByAcct(
|
export async function searchProfilesByAcct(
|
||||||
|
authToken: string | null,
|
||||||
acct: string,
|
acct: string,
|
||||||
|
resolve: boolean = false,
|
||||||
|
limit = 40,
|
||||||
): Promise<Profile[]> {
|
): Promise<Profile[]> {
|
||||||
const url = `${BACKEND_URL}/api/v1/accounts/search`
|
const url = `${BACKEND_URL}/api/v1/accounts/search`
|
||||||
const response = await http(url, {
|
const response = await http(url, {
|
||||||
method: "GET",
|
method: "GET",
|
||||||
queryParams: { q: acct },
|
queryParams: { q: acct, resolve, limit },
|
||||||
|
authToken,
|
||||||
})
|
})
|
||||||
const data = await response.json()
|
const data = await response.json()
|
||||||
if (response.status !== 200) {
|
if (response.status !== 200) {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { BACKEND_URL } from "@/constants"
|
import { BACKEND_URL } from "@/constants"
|
||||||
import { http } from "./common"
|
import { http } from "./common"
|
||||||
import { User } from "./users"
|
import { Aliases, User } from "./users"
|
||||||
|
|
||||||
export async function changePassword(
|
export async function changePassword(
|
||||||
authToken: string,
|
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) {
|
async function downloadBlob(blob: Blob, name: string) {
|
||||||
const fileUrl = window.URL.createObjectURL(blob)
|
const fileUrl = window.URL.createObjectURL(blob)
|
||||||
const hiddenLink = document.createElement("a")
|
const hiddenLink = document.createElement("a")
|
||||||
|
|
|
@ -194,7 +194,7 @@ async function identifySender() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
isLoading = true
|
isLoading = true
|
||||||
const profiles = await searchProfilesByAcct(senderAcct)
|
const profiles = await searchProfilesByAcct(null, senderAcct)
|
||||||
if (profiles.length > 1) {
|
if (profiles.length > 1) {
|
||||||
senderError = "Please provide full address"
|
senderError = "Please provide full address"
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -22,9 +22,40 @@
|
||||||
<profile-list-item :profile="profile"></profile-list-item>
|
<profile-list-item :profile="profile"></profile-list-item>
|
||||||
</router-link>
|
</router-link>
|
||||||
</section>
|
</section>
|
||||||
<div class="not-found" v-if="isEmpty() && !isLoading">
|
<section>
|
||||||
No aliases found
|
<h2>Add alias</h2>
|
||||||
</div>
|
<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>
|
<loader v-if="isLoading"></loader>
|
||||||
</template>
|
</template>
|
||||||
</sidebar-layout>
|
</sidebar-layout>
|
||||||
|
@ -34,16 +65,21 @@
|
||||||
import { onMounted } from "vue"
|
import { onMounted } from "vue"
|
||||||
import { $, $ref } from "vue/macros"
|
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 SidebarLayout from "@/components/SidebarLayout.vue"
|
||||||
import Loader from "@/components/Loader.vue"
|
import Loader from "@/components/Loader.vue"
|
||||||
import ProfileListItem from "@/components/ProfileListItem.vue"
|
import ProfileListItem from "@/components/ProfileListItem.vue"
|
||||||
import { useCurrentUser } from "@/store/user"
|
import { useCurrentUser } from "@/store/user"
|
||||||
|
|
||||||
const { ensureCurrentUser } = $(useCurrentUser())
|
const { ensureCurrentUser, ensureAuthToken } = $(useCurrentUser())
|
||||||
|
|
||||||
let aliases = $ref<Aliases>({ declared: [], verified: [] })
|
let aliases = $ref<Aliases>({ declared: [], verified: [] })
|
||||||
let isLoading = $ref(false)
|
let isLoading = $ref(false)
|
||||||
|
let newAlias = $ref<string>("")
|
||||||
|
let newAliasSuggestions = $ref<Profile[]>([])
|
||||||
|
let newAliasError = $ref<string | null>(null)
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
isLoading = true
|
isLoading = true
|
||||||
|
@ -51,13 +87,37 @@ onMounted(async () => {
|
||||||
isLoading = false
|
isLoading = false
|
||||||
})
|
})
|
||||||
|
|
||||||
function isEmpty(): boolean {
|
function canAddAlias(): boolean {
|
||||||
return aliases.declared.length === 0 && aliases.verified.length === 0
|
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>
|
</script>
|
||||||
|
|
||||||
<style scoped lang="scss">
|
<style scoped lang="scss">
|
||||||
@import "../styles/layout";
|
@import "../styles/layout";
|
||||||
|
@import "../styles/mixins";
|
||||||
|
@import "../styles/theme";
|
||||||
|
|
||||||
section {
|
section {
|
||||||
margin-bottom: $block-outer-padding;
|
margin-bottom: $block-outer-padding;
|
||||||
|
@ -67,6 +127,32 @@ section {
|
||||||
margin-bottom: $block-outer-padding;
|
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 {
|
.loader {
|
||||||
margin: $block-outer-padding auto;
|
margin: $block-outer-padding auto;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue