Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F85828628
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Authored By
Unknown
Size
22 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/src/boot/after_store.js b/src/boot/after_store.js
index 90f2530263..90c558f6ca 100644
--- a/src/boot/after_store.js
+++ b/src/boot/after_store.js
@@ -1,178 +1,180 @@
import Vue from 'vue'
import VueRouter from 'vue-router'
import App from '../App.vue'
import PublicTimeline from '../components/public_timeline/public_timeline.vue'
import PublicAndExternalTimeline from '../components/public_and_external_timeline/public_and_external_timeline.vue'
import FriendsTimeline from '../components/friends_timeline/friends_timeline.vue'
import TagTimeline from '../components/tag_timeline/tag_timeline.vue'
import ConversationPage from '../components/conversation-page/conversation-page.vue'
import Mentions from '../components/mentions/mentions.vue'
import DMs from '../components/dm_timeline/dm_timeline.vue'
import UserProfile from '../components/user_profile/user_profile.vue'
import Settings from '../components/settings/settings.vue'
import Registration from '../components/registration/registration.vue'
import UserSettings from '../components/user_settings/user_settings.vue'
import FollowRequests from '../components/follow_requests/follow_requests.vue'
import OAuthCallback from '../components/oauth_callback/oauth_callback.vue'
+import UserSearch from '../components/user_search/user_search.vue'
const afterStoreSetup = ({store, i18n}) => {
window.fetch('/api/statusnet/config.json')
.then((res) => res.json())
.then((data) => {
const {name, closed: registrationClosed, textlimit, server} = data.site
store.dispatch('setInstanceOption', { name: 'name', value: name })
store.dispatch('setInstanceOption', { name: 'registrationOpen', value: (registrationClosed === '0') })
store.dispatch('setInstanceOption', { name: 'textlimit', value: parseInt(textlimit) })
store.dispatch('setInstanceOption', { name: 'server', value: server })
var apiConfig = data.site.pleromafe
window.fetch('/static/config.json')
.then((res) => res.json())
.catch((err) => {
console.warn('Failed to load static/config.json, continuing without it.')
console.warn(err)
return {}
})
.then((staticConfig) => {
// This takes static config and overrides properties that are present in apiConfig
var config = Object.assign({}, staticConfig, apiConfig)
var theme = (config.theme)
var background = (config.background)
var hidePostStats = (config.hidePostStats)
var hideUserStats = (config.hideUserStats)
var logo = (config.logo)
var logoMask = (typeof config.logoMask === 'undefined' ? true : config.logoMask)
var logoMargin = (typeof config.logoMargin === 'undefined' ? 0 : config.logoMargin)
var redirectRootNoLogin = (config.redirectRootNoLogin)
var redirectRootLogin = (config.redirectRootLogin)
var chatDisabled = (config.chatDisabled)
var showInstanceSpecificPanel = (config.showInstanceSpecificPanel)
var scopeOptionsEnabled = (config.scopeOptionsEnabled)
var formattingOptionsEnabled = (config.formattingOptionsEnabled)
var collapseMessageWithSubject = (config.collapseMessageWithSubject)
var loginMethod = (config.loginMethod)
store.dispatch('setInstanceOption', { name: 'theme', value: theme })
store.dispatch('setInstanceOption', { name: 'background', value: background })
store.dispatch('setInstanceOption', { name: 'hidePostStats', value: hidePostStats })
store.dispatch('setInstanceOption', { name: 'hideUserStats', value: hideUserStats })
store.dispatch('setInstanceOption', { name: 'logo', value: logo })
store.dispatch('setInstanceOption', { name: 'logoMask', value: logoMask })
store.dispatch('setInstanceOption', { name: 'logoMargin', value: logoMargin })
store.dispatch('setInstanceOption', { name: 'redirectRootNoLogin', value: redirectRootNoLogin })
store.dispatch('setInstanceOption', { name: 'redirectRootLogin', value: redirectRootLogin })
store.dispatch('setInstanceOption', { name: 'showInstanceSpecificPanel', value: showInstanceSpecificPanel })
store.dispatch('setInstanceOption', { name: 'scopeOptionsEnabled', value: scopeOptionsEnabled })
store.dispatch('setInstanceOption', { name: 'formattingOptionsEnabled', value: formattingOptionsEnabled })
store.dispatch('setInstanceOption', { name: 'collapseMessageWithSubject', value: collapseMessageWithSubject })
store.dispatch('setInstanceOption', { name: 'loginMethod', value: loginMethod })
if (chatDisabled) {
store.dispatch('disableChat')
}
const routes = [
{ name: 'root',
path: '/',
redirect: to => {
return (store.state.users.currentUser
? store.state.instance.redirectRootLogin
: store.state.instance.redirectRootNoLogin) || '/main/all'
}},
{ path: '/main/all', component: PublicAndExternalTimeline },
{ path: '/main/public', component: PublicTimeline },
{ path: '/main/friends', component: FriendsTimeline },
{ path: '/tag/:tag', component: TagTimeline },
{ name: 'conversation', path: '/notice/:id', component: ConversationPage, meta: { dontScroll: true } },
{ name: 'user-profile', path: '/users/:id', component: UserProfile },
{ name: 'mentions', path: '/:username/mentions', component: Mentions },
{ name: 'dms', path: '/:username/dms', component: DMs },
{ name: 'settings', path: '/settings', component: Settings },
{ name: 'registration', path: '/registration', component: Registration },
{ name: 'registration', path: '/registration/:token', component: Registration },
{ name: 'friend-requests', path: '/friend-requests', component: FollowRequests },
{ name: 'user-settings', path: '/user-settings', component: UserSettings },
- { name: 'oauth-callback', path: '/oauth-callback', component: OAuthCallback, props: (route) => ({ code: route.query.code }) }
+ { name: 'oauth-callback', path: '/oauth-callback', component: OAuthCallback, props: (route) => ({ code: route.query.code }) },
+ { name: 'user-search', path: '/user-search', component: UserSearch, props: (route) => ({ query: route.query.query }) }
]
const router = new VueRouter({
mode: 'history',
routes,
scrollBehavior: (to, from, savedPosition) => {
if (to.matched.some(m => m.meta.dontScroll)) {
return false
}
return savedPosition || { x: 0, y: 0 }
}
})
/* eslint-disable no-new */
new Vue({
router,
store,
i18n,
el: '#app',
render: h => h(App)
})
})
})
window.fetch('/static/terms-of-service.html')
.then((res) => res.text())
.then((html) => {
store.dispatch('setInstanceOption', { name: 'tos', value: html })
})
window.fetch('/api/pleroma/emoji.json')
.then(
(res) => res.json()
.then(
(values) => {
const emoji = Object.keys(values).map((key) => {
return { shortcode: key, image_url: values[key] }
})
store.dispatch('setInstanceOption', { name: 'customEmoji', value: emoji })
store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: true })
},
(failure) => {
store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: false })
}
),
(error) => console.log(error)
)
window.fetch('/static/emoji.json')
.then((res) => res.json())
.then((values) => {
const emoji = Object.keys(values).map((key) => {
return { shortcode: key, image_url: false, 'utf': values[key] }
})
store.dispatch('setInstanceOption', { name: 'emoji', value: emoji })
})
window.fetch('/instance/panel.html')
.then((res) => res.text())
.then((html) => {
store.dispatch('setInstanceOption', { name: 'instanceSpecificPanelContent', value: html })
})
window.fetch('/nodeinfo/2.0.json')
.then((res) => res.json())
.then((data) => {
const metadata = data.metadata
const features = metadata.features
store.dispatch('setInstanceOption', { name: 'mediaProxyAvailable', value: features.includes('media_proxy') })
store.dispatch('setInstanceOption', { name: 'chatAvailable', value: features.includes('chat') })
store.dispatch('setInstanceOption', { name: 'gopherAvailable', value: features.includes('gopher') })
const suggestions = metadata.suggestions
store.dispatch('setInstanceOption', { name: 'suggestionsEnabled', value: suggestions.enabled })
store.dispatch('setInstanceOption', { name: 'suggestionsWeb', value: suggestions.web })
})
}
export default afterStoreSetup
diff --git a/src/components/user_finder/user_finder.js b/src/components/user_finder/user_finder.js
index a743b5f666..74f79d1bab 100644
--- a/src/components/user_finder/user_finder.js
+++ b/src/components/user_finder/user_finder.js
@@ -1,33 +1,18 @@
const UserFinder = {
data: () => ({
username: undefined,
hidden: true,
error: false,
loading: false
}),
methods: {
findUser (username) {
- username = username[0] === '@' ? username.slice(1) : username
- this.loading = true
- this.$store.state.api.backendInteractor.externalProfile(username)
- .then((user) => {
- this.loading = false
- this.hidden = true
- if (!user.error) {
- this.$store.commit('addNewUsers', [user])
- this.$router.push({name: 'user-profile', params: {id: user.id}})
- } else {
- this.error = true
- }
- })
+ this.$router.push({ name: 'user-search', query: { query: username } })
},
toggleHidden () {
this.hidden = !this.hidden
- },
- dismissError () {
- this.error = false
}
}
}
export default UserFinder
diff --git a/src/components/user_finder/user_finder.vue b/src/components/user_finder/user_finder.vue
index 69bd1d210a..f25565697a 100644
--- a/src/components/user_finder/user_finder.vue
+++ b/src/components/user_finder/user_finder.vue
@@ -1,31 +1,27 @@
<template>
<span class="user-finder-container">
- <span class="alert error" v-if="error">
- <i class="icon-cancel user-finder-icon" @click="dismissError"/>
- {{$t('finder.error_fetching_user')}}
- </span>
<i class="icon-spin4 user-finder-icon animate-spin-slow" v-if="loading" />
<a href="#" v-if="hidden"><i class="icon-user-plus user-finder-icon" @click.prevent.stop="toggleHidden"/></a>
<span v-else>
<input class="user-finder-input" @keyup.enter="findUser(username)" v-model="username" :placeholder="$t('finder.find_user')" id="user-finder-input" type="text"/>
<i class="icon-cancel user-finder-icon" @click.prevent.stop="toggleHidden"/>
</span>
</span>
</template>
<script src="./user_finder.js"></script>
<style lang="scss">
@import '../../_variables.scss';
.user-finder-container {
height: 29px;
max-width: 100%;
}
.user-finder-input {
max-width: 80%;
vertical-align: middle;
}
</style>
diff --git a/src/components/user_search/user_search.js b/src/components/user_search/user_search.js
new file mode 100644
index 0000000000..1e488f0c93
--- /dev/null
+++ b/src/components/user_search/user_search.js
@@ -0,0 +1,33 @@
+import UserCard from '../user_card/user_card.vue'
+import userSearchApi from '../../services/new_api/user_search.js'
+const userSearch = {
+ components: {
+ UserCard
+ },
+ props: [
+ 'query'
+ ],
+ data () {
+ return {
+ users: []
+ }
+ },
+ mounted () {
+ this.search(this.query)
+ },
+ watch: {
+ query (newV) {
+ this.search(newV)
+ }
+ },
+ methods: {
+ search (query) {
+ userSearchApi.search({query, store: this.$store})
+ .then((res) => {
+ this.users = res
+ })
+ }
+ }
+}
+
+export default userSearch
diff --git a/src/components/user_search/user_search.vue b/src/components/user_search/user_search.vue
new file mode 100644
index 0000000000..1624ebef38
--- /dev/null
+++ b/src/components/user_search/user_search.vue
@@ -0,0 +1,12 @@
+<template>
+ <div class="user-seach panel panel-default">
+ <div class="panel-heading">
+ {{$t('nav.user_search')}}
+ </div>
+ <div class="panel-body">
+ <user-card v-for="user in users" :key="user.id" :user="user" :showFollows="true"></user-card>
+ </div>
+ </div>
+</template>
+
+<script src="./user_search.js"></script>
diff --git a/src/i18n/en.json b/src/i18n/en.json
index cadbaf9534..4201ba2273 100644
--- a/src/i18n/en.json
+++ b/src/i18n/en.json
@@ -1,203 +1,204 @@
{
"chat": {
"title": "Chat"
},
"features_panel": {
"chat": "Chat",
"gopher": "Gopher",
"media_proxy": "Media proxy",
"scope_options": "Scope options",
"text_limit": "Text limit",
"title": "Features",
"who_to_follow": "Who to follow"
},
"finder": {
"error_fetching_user": "Error fetching user",
"find_user": "Find user"
},
"general": {
"apply": "Apply",
"submit": "Submit"
},
"login": {
"login": "Log in",
"description": "Log in with OAuth",
"logout": "Log out",
"password": "Password",
"placeholder": "e.g. lain",
"register": "Register",
"username": "Username"
},
"nav": {
"chat": "Local Chat",
"friend_requests": "Follow Requests",
"mentions": "Mentions",
"dms": "Direct Messages",
"public_tl": "Public Timeline",
"timeline": "Timeline",
- "twkn": "The Whole Known Network"
+ "twkn": "The Whole Known Network",
+ "user_search": "User Search"
},
"notifications": {
"broken_favorite": "Unknown status, searching for it...",
"favorited_you": "favorited your status",
"followed_you": "followed you",
"load_older": "Load older notifications",
"notifications": "Notifications",
"read": "Read!",
"repeated_you": "repeated your status"
},
"post_status": {
"account_not_locked_warning": "Your account is not {0}. Anyone can follow you to view your follower-only posts.",
"account_not_locked_warning_link": "locked",
"attachments_sensitive": "Mark attachments as sensitive",
"content_type": {
"plain_text": "Plain text"
},
"content_warning": "Subject (optional)",
"default": "Just landed in L.A.",
"direct_warning": "This post will only be visible to all the mentioned users.",
"posting": "Posting",
"scope": {
"direct": "Direct - Post to mentioned users only",
"private": "Followers-only - Post to followers only",
"public": "Public - Post to public timelines",
"unlisted": "Unlisted - Do not post to public timelines"
}
},
"registration": {
"bio": "Bio",
"email": "Email",
"fullname": "Display name",
"password_confirm": "Password confirmation",
"registration": "Registration",
"token": "Invite token"
},
"settings": {
"attachmentRadius": "Attachments",
"attachments": "Attachments",
"autoload": "Enable automatic loading when scrolled to the bottom",
"avatar": "Avatar",
"avatarAltRadius": "Avatars (Notifications)",
"avatarRadius": "Avatars",
"background": "Background",
"bio": "Bio",
"btnRadius": "Buttons",
"cBlue": "Blue (Reply, follow)",
"cGreen": "Green (Retweet)",
"cOrange": "Orange (Favorite)",
"cRed": "Red (Cancel)",
"change_password": "Change Password",
"change_password_error": "There was an issue changing your password.",
"changed_password": "Password changed successfully!",
"collapse_subject": "Collapse posts with subjects",
"confirm_new_password": "Confirm new password",
"current_avatar": "Your current avatar",
"current_password": "Current password",
"current_profile_banner": "Your current profile banner",
"data_import_export_tab": "Data Import / Export",
"default_vis": "Default visibility scope",
"delete_account": "Delete Account",
"delete_account_description": "Permanently delete your account and all your messages.",
"delete_account_error": "There was an issue deleting your account. If this persists please contact your instance administrator.",
"delete_account_instructions": "Type your password in the input below to confirm account deletion.",
"export_theme": "Save preset",
"filtering": "Filtering",
"filtering_explanation": "All statuses containing these words will be muted, one per line",
"follow_export": "Follow export",
"follow_export_button": "Export your follows to a csv file",
"follow_export_processing": "Processing, you'll soon be asked to download your file",
"follow_import": "Follow import",
"follow_import_error": "Error importing followers",
"follows_imported": "Follows imported! Processing them will take a while.",
"foreground": "Foreground",
"general": "General",
"hide_attachments_in_convo": "Hide attachments in conversations",
"hide_attachments_in_tl": "Hide attachments in timeline",
"hide_post_stats": "Hide post statistics (e.g. the number of favorites)",
"hide_user_stats": "Hide user statistics (e.g. the number of followers)",
"import_followers_from_a_csv_file": "Import follows from a csv file",
"import_theme": "Load preset",
"inputRadius": "Input fields",
"instance_default": "(default: {value})",
"interfaceLanguage": "Interface language",
"invalid_theme_imported": "The selected file is not a supported Pleroma theme. No changes to your theme were made.",
"limited_availability": "Unavailable in your browser",
"links": "Links",
"lock_account_description": "Restrict your account to approved followers only",
"loop_video": "Loop videos",
"loop_video_silent_only": "Loop only videos without sound (i.e. Mastodon's \"gifs\")",
"name": "Name",
"name_bio": "Name & Bio",
"new_password": "New password",
"notification_visibility": "Types of notifications to show",
"notification_visibility_follows": "Follows",
"notification_visibility_likes": "Likes",
"notification_visibility_mentions": "Mentions",
"notification_visibility_repeats": "Repeats",
"no_rich_text_description": "Strip rich text formatting from all posts",
"nsfw_clickthrough": "Enable clickthrough NSFW attachment hiding",
"panelRadius": "Panels",
"pause_on_unfocused": "Pause streaming when tab is not focused",
"presets": "Presets",
"profile_background": "Profile Background",
"profile_banner": "Profile Banner",
"profile_tab": "Profile",
"radii_help": "Set up interface edge rounding (in pixels)",
"replies_in_timeline": "Replies in timeline",
"reply_link_preview": "Enable reply-link preview on mouse hover",
"reply_visibility_all": "Show all replies",
"reply_visibility_following": "Only show replies directed at me or users I'm following",
"reply_visibility_self": "Only show replies directed at me",
"saving_err": "Error saving settings",
"saving_ok": "Settings saved",
"security_tab": "Security",
"set_new_avatar": "Set new avatar",
"set_new_profile_background": "Set new profile background",
"set_new_profile_banner": "Set new profile banner",
"settings": "Settings",
"stop_gifs": "Play-on-hover GIFs",
"streaming": "Enable automatic streaming of new posts when scrolled to the top",
"text": "Text",
"theme": "Theme",
"theme_help": "Use hex color codes (#rrggbb) to customize your color theme.",
"tooltipRadius": "Tooltips/alerts",
"user_settings": "User Settings",
"values": {
"false": "no",
"true": "yes"
}
},
"timeline": {
"collapse": "Collapse",
"conversation": "Conversation",
"error_fetching": "Error fetching updates",
"load_older": "Load older statuses",
"no_retweet_hint": "Post is marked as followers-only or direct and cannot be repeated",
"repeated": "repeated",
"show_new": "Show new",
"up_to_date": "Up-to-date"
},
"user_card": {
"approve": "Approve",
"block": "Block",
"blocked": "Blocked!",
"deny": "Deny",
"follow": "Follow",
"followees": "Following",
"followers": "Followers",
"following": "Following!",
"follows_you": "Follows you!",
"mute": "Mute",
"muted": "Muted",
"per_day": "per day",
"remote_follow": "Remote follow",
"statuses": "Statuses"
},
"user_profile": {
"timeline_title": "User Timeline"
},
"who_to_follow": {
"more": "More",
"who_to_follow": "Who to follow"
}
}
diff --git a/src/services/new_api/user_search.js b/src/services/new_api/user_search.js
new file mode 100644
index 0000000000..ce7da88e4d
--- /dev/null
+++ b/src/services/new_api/user_search.js
@@ -0,0 +1,16 @@
+import utils from './utils.js'
+
+const search = ({query, store}) => {
+ return utils.request({
+ store,
+ url: '/api/pleroma/search_user',
+ params: {
+ query
+ }
+ }).then((data) => data.json())
+}
+const UserSearch = {
+ search
+}
+
+export default UserSearch
diff --git a/src/services/new_api/utils.js b/src/services/new_api/utils.js
new file mode 100644
index 0000000000..078f392fc0
--- /dev/null
+++ b/src/services/new_api/utils.js
@@ -0,0 +1,36 @@
+const queryParams = (params) => {
+ return Object.keys(params)
+ .map(k => encodeURIComponent(k) + '=' + encodeURIComponent(params[k]))
+ .join('&')
+}
+
+const headers = (store) => {
+ const accessToken = store.state.oauth.token
+ if (accessToken) {
+ return {'Authorization': `Bearer ${accessToken}`}
+ } else {
+ return {}
+ }
+}
+
+const request = ({method = 'GET', url, params, store}) => {
+ const instance = store.state.instance.server
+ let fullUrl = `${instance}${url}`
+
+ if (method === 'GET' && params) {
+ fullUrl = fullUrl + `?${queryParams(params)}`
+ }
+
+ return window.fetch(fullUrl, {
+ method,
+ headers: headers(store),
+ credentials: 'same-origin'
+ })
+}
+
+const utils = {
+ queryParams,
+ request
+}
+
+export default utils
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Oct 31, 9:57 AM (20 h, 47 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1801239
Default Alt Text
(22 KB)
Attached To
Mode
rPUFE pleroma-fe-upstream
Attached
Detach File
Event Timeline