]> Untitled Git - lemmy.git/commitdiff
Changing federated community and user links and searching.
authorDessalines <tyhou13@gmx.com>
Thu, 30 Apr 2020 15:45:12 +0000 (11:45 -0400)
committerDessalines <tyhou13@gmx.com>
Thu, 30 Apr 2020 15:45:12 +0000 (11:45 -0400)
- Search: !community@instance, @user@instance
- Representation: community@instance, user@instance

README.md
docs/src/about_guide.md
server/src/apub/fetcher.rs
ui/src/api_tests/api.spec.ts
ui/src/components/community-link.tsx
ui/src/components/sidebar.tsx
ui/src/components/user-listing.tsx
ui/src/components/user.tsx
ui/src/utils.ts

index 723d535ff0d796a600a80c4f047d92471f746631..a4a69cab0923a246cf6ac112ca3c1eda40684015 100644 (file)
--- a/README.md
+++ b/README.md
@@ -73,7 +73,7 @@ Each lemmy server can set its own moderation policy; appointing site-wide admins
   - Full vote scores `(+/-)` like old reddit.
   - Themes, including light, dark, and solarized.
   - Emojis with autocomplete support. Start typing `:`
-  - User tagging using `@`, Community tagging using `#`.
+  - User tagging using `@`, Community tagging using `!`.
   - Integrated image uploading in both posts and comments.
   - A post can consist of a title and any combination of self text, a URL, or nothing else.
   - Notifications, on comment replies and when you're tagged.
index 16788ab93733ce4062e74f89886b14db64092a41..6f709b580d11e8189814020cc460b48a5455ad27 100644 (file)
@@ -3,7 +3,7 @@
 Start typing...
 
 - `@a_user_name` to get a list of usernames.
-- `#a_community` to get a list of communities.
+- `!a_community` to get a list of communities.
 - `:emoji` to get a list of emojis.
 
 ## Sorting
index 2164dec8b46dfb0ab779c6dec9fa0260deeaafd2..8e82a2f79113503f1466b8e7a7dfe4be59e9ba3e 100644 (file)
@@ -45,14 +45,31 @@ pub enum SearchAcceptedObjects {
 /// Attempt to parse the query as URL, and fetch an ActivityPub object from it.
 ///
 /// Some working examples for use with the docker/federation/ setup:
-/// http://lemmy_alpha:8540/c/main, or /c/main@lemmy_alpha:8540
-/// http://lemmy_alpha:8540/u/lemmy_alpha, or /u/lemmy_alpha@lemmy_alpha:8540
+/// http://lemmy_alpha:8540/c/main, or !main@lemmy_alpha:8540
+/// http://lemmy_alpha:8540/u/lemmy_alpha, or @lemmy_alpha@lemmy_alpha:8540
 /// http://lemmy_alpha:8540/p/3
 pub fn search_by_apub_id(query: &str, conn: &PgConnection) -> Result<SearchResponse, Error> {
   // Parse the shorthand query url
   let query_url = if query.contains('@') {
+    debug!("{}", query);
     let split = query.split('@').collect::<Vec<&str>>();
-    let url = format!("{}://{}{}", get_apub_protocol_string(), split[1], split[0]);
+
+    // User type will look like ['', username, instance]
+    // Community will look like [!community, instance]
+    let (name, instance) = if split.len() == 3 {
+      (format!("/u/{}", split[1]), split[2])
+    } else if split.len() == 2 {
+      if split[0].contains('!') {
+        let split2 = split[0].split('!').collect::<Vec<&str>>();
+        (format!("/c/{}", split2[1]), split[1])
+      } else {
+        return Err(format_err!("Invalid search query: {}", query));
+      }
+    } else {
+      return Err(format_err!("Invalid search query: {}", query));
+    };
+
+    let url = format!("{}://{}{}", get_apub_protocol_string(), instance, name);
     Url::parse(&url)?
   } else {
     Url::parse(&query)?
index 7a810d9a00d2b455dc52cb117325bba20a053ff7..7121d038b1d26e5b9dff7225bb090136c591419b 100644 (file)
@@ -96,7 +96,7 @@ describe('main', () => {
     test('/u/lemmy_alpha follows and accepts lemmy_beta/c/main', async () => {
       // Make sure lemmy_beta/c/main is cached on lemmy_alpha
       // Use short-hand search url
-      let searchUrl = `${lemmyAlphaApiUrl}/search?q=/c/main@lemmy_beta:8550&type_=All&sort=TopAll`;
+      let searchUrl = `${lemmyAlphaApiUrl}/search?q=!main@lemmy_beta:8550&type_=All&sort=TopAll`;
 
       let searchResponse: SearchResponse = await fetch(searchUrl, {
         method: 'GET',
index bcfa053446d689bbca02ed4fe6aecf70cd102c54..eb55400e159c422b49c481a46a639a3fd558781c 100644 (file)
@@ -12,6 +12,7 @@ interface CommunityOther {
 
 interface CommunityLinkProps {
   community: Community | CommunityOther;
+  realLink?: boolean;
 }
 
 export class CommunityLink extends Component<CommunityLinkProps, any> {
@@ -27,8 +28,10 @@ export class CommunityLink extends Component<CommunityLinkProps, any> {
       name_ = community.name;
       link = `/c/${community.name}`;
     } else {
-      name_ = `${hostname(community.actor_id)}/${community.name}`;
-      link = `/community/${community.id}`;
+      name_ = `${community.name}@${hostname(community.actor_id)}`;
+      link = !this.props.realLink
+        ? `/community/${community.id}`
+        : community.actor_id;
     }
     return <Link to={link}>{name_}</Link>;
   }
index 517669230f8c758309dd0b5d1f0008f9000d89e2..dc2376d7ce018982394a9c2446565631a7b620c3 100644 (file)
@@ -11,6 +11,7 @@ import { WebSocketService, UserService } from '../services';
 import { mdToHtml, getUnixTime, hostname } from '../utils';
 import { CommunityForm } from './community-form';
 import { UserListing } from './user-listing';
+import { CommunityLink } from './community-link';
 import { i18n } from '../i18next';
 
 interface SidebarProps {
@@ -66,7 +67,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
       name_ = community.name;
       link = `/c/${community.name}`;
     } else {
-      name_ = `${hostname(community.actor_id)}/${community.name}`;
+      name_ = `${community.name}@${hostname(community.actor_id)}`;
       link = community.actor_id;
     }
     return (
@@ -86,15 +87,7 @@ export class Sidebar extends Component<SidebarProps, SidebarState> {
                 </small>
               )}
             </h5>
-            {community.local ? (
-              <Link className="text-muted" to={link}>
-                {name_}
-              </Link>
-            ) : (
-              <a className="text-muted" href={link} target="_blank">
-                {name_}
-              </a>
-            )}
+            <CommunityLink community={community} realLink />
             <ul class="list-inline mb-1 text-muted font-weight-bold">
               {this.canMod && (
                 <>
index 356c4d4847797436b96d3794217731383497c2ac..903aa1a7550638da52250f2399eedc963afbb4cf 100644 (file)
@@ -13,6 +13,7 @@ interface UserOther {
 
 interface UserListingProps {
   user: UserView | UserOther;
+  realLink?: boolean;
 }
 
 export class UserListing extends Component<UserListingProps, any> {
@@ -29,8 +30,8 @@ export class UserListing extends Component<UserListingProps, any> {
       name_ = user.name;
       link = `/u/${user.name}`;
     } else {
-      name_ = `${hostname(user.actor_id)}/${user.name}`;
-      link = `/user/${user.id}`;
+      name_ = `${user.name}@${hostname(user.actor_id)}`;
+      link = !this.props.realLink ? `/user/${user.id}` : user.actor_id;
     }
 
     return (
index b3e4542f548e2a03e2216c48766ec15eb3d42af4..51b9582fecf4bf2b09ebe891fee83e12e6285509 100644 (file)
@@ -402,7 +402,7 @@ export class User extends Component<any, UserState> {
             <h5>
               <ul class="list-inline mb-0">
                 <li className="list-inline-item">
-                  <UserListing user={user} />
+                  <UserListing user={user} realLink />
                 </li>
                 {user.banned && (
                   <li className="list-inline-item badge badge-danger">
index 480b41c7c313a6ffcd6403456583b4ee14fe2ee9..277da9874bcb298bbb5801709c4347e403d2f0fe 100644 (file)
@@ -501,7 +501,10 @@ export function setupTribute(): Tribute {
       {
         trigger: '@',
         selectTemplate: (item: any) => {
-          return `[/u/${item.original.key}](/u/${item.original.key})`;
+          let link = item.original.local
+            ? `[@${item.original.key}](/u/${item.original.key})`
+            : `[@${item.original.key}](/user/${item.original.id})`;
+          return link;
         },
         values: (text: string, cb: any) => {
           userSearch(text, (users: any) => cb(users));
@@ -514,9 +517,12 @@ export function setupTribute(): Tribute {
 
       // Communities
       {
-        trigger: '#',
+        trigger: '!',
         selectTemplate: (item: any) => {
-          return `[/c/${item.original.key}](/c/${item.original.key})`;
+          let link = item.original.local
+            ? `[!${item.original.key}](/c/${item.original.key})`
+            : `[!${item.original.key}](/community/${item.original.id})`;
+          return link;
         },
         values: (text: string, cb: any) => {
           communitySearch(text, (communities: any) => cb(communities));
@@ -559,7 +565,12 @@ function userSearch(text: string, cb: any) {
         if (res.op == UserOperation.Search) {
           let data = res.data as SearchResponse;
           let users = data.users.map(u => {
-            return { key: u.name };
+            let name_ = u.local ? u.name : `${u.name}@${hostname(u.actor_id)}`;
+            return {
+              key: name_,
+              local: u.local,
+              id: u.id,
+            };
           });
           cb(users);
           this.userSub.unsubscribe();
@@ -590,8 +601,13 @@ function communitySearch(text: string, cb: any) {
         let res = wsJsonToRes(msg);
         if (res.op == UserOperation.Search) {
           let data = res.data as SearchResponse;
-          let communities = data.communities.map(u => {
-            return { key: u.name };
+          let communities = data.communities.map(c => {
+            let name_ = c.local ? c.name : `${c.name}@${hostname(c.actor_id)}`;
+            return {
+              key: name_,
+              local: c.local,
+              id: c.id,
+            };
           });
           cb(communities);
           this.communitySub.unsubscribe();