mirror of
https://github.com/coracle-social/coracle.git
synced 2024-09-29 08:21:20 +00:00
Rank groups by wot
This commit is contained in:
parent
b0028ce216
commit
5b33a1cdc3
@ -5,6 +5,7 @@
|
||||
- [x] Accept npubs in people input
|
||||
- [x] Skip notifying admin when the person joining/leaving groups is the admin
|
||||
- [x] Remove group share modal, skip straight to create invite link
|
||||
- [x] Rank groups by WoT
|
||||
|
||||
# 0.4.4
|
||||
|
||||
|
@ -69,7 +69,7 @@
|
||||
"normalize-url": "^8.0.0",
|
||||
"nostr-tools": "^2.1.5",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"paravel": "^0.5.4",
|
||||
"paravel": "^0.5.5",
|
||||
"qr-scanner": "^1.4.2",
|
||||
"qrcode": "^1.5.3",
|
||||
"ramda": "^0.29.1",
|
||||
|
@ -3,13 +3,15 @@
|
||||
import Chip from "src/partials/Chip.svelte"
|
||||
import Card from "src/partials/Card.svelte"
|
||||
import GroupCircle from "src/app/shared/GroupCircle.svelte"
|
||||
import PersonCircles from "src/app/shared/PersonCircles.svelte"
|
||||
import {router} from "src/app/router"
|
||||
import {displayGroup, deriveGroup} from "src/engine"
|
||||
import {displayGroup, deriveGroup, getWotGroupMembers} from "src/engine"
|
||||
|
||||
export let address
|
||||
export let modal = false
|
||||
|
||||
const group = deriveGroup(address)
|
||||
const members = getWotGroupMembers(address)
|
||||
|
||||
const enter = () => {
|
||||
const route = router.at("groups").of(address).at("notes")
|
||||
@ -43,5 +45,9 @@
|
||||
{ellipsize($group.meta.about, 300)}
|
||||
</p>
|
||||
{/if}
|
||||
{#if members.length > 0}
|
||||
<p class="mt-4 text-lg text-neutral-300">Members:</p>
|
||||
<PersonCircles pubkeys={members.slice(0, 20)} />
|
||||
{/if}
|
||||
</div>
|
||||
</Card>
|
||||
|
@ -1,4 +1,5 @@
|
||||
<script lang="ts">
|
||||
import cx from "classnames"
|
||||
import PersonCircle from "src/app/shared/PersonCircle.svelte"
|
||||
|
||||
export let pubkeys
|
||||
@ -6,10 +7,10 @@
|
||||
const klass = $$props.class || "w-8 h-8"
|
||||
</script>
|
||||
|
||||
<div class="flex">
|
||||
<div class="flex pr-3">
|
||||
{#each pubkeys as pubkey (pubkey)}
|
||||
<div class="z-feature -mr-3 inline-block">
|
||||
<PersonCircle class={klass} {pubkey} />
|
||||
<PersonCircle class={cx(klass, "border border-solid border-neutral-800")} {pubkey} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
|
@ -7,7 +7,7 @@
|
||||
import Popover from "src/partials/Popover.svelte"
|
||||
import Modal from "src/partials/Modal.svelte"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
import PersonCircle from "src/app/shared/PersonCircle.svelte"
|
||||
import PersonCircles from "src/app/shared/PersonCircles.svelte"
|
||||
import PersonAbout from "src/app/shared/PersonAbout.svelte"
|
||||
import NoteContent from "src/app/shared/NoteContent.svelte"
|
||||
import {router} from "src/app/router"
|
||||
@ -81,13 +81,7 @@
|
||||
<div slot="header" class="flex h-16 items-start gap-4 overflow-hidden p-1 px-4">
|
||||
<div class="flex items-center gap-4 pt-1">
|
||||
<Anchor class="fa fa-arrow-left cursor-pointer text-2xl" href="/channels" />
|
||||
<div class="mr-3 flex pt-1">
|
||||
{#each pubkeys as pubkey (pubkey)}
|
||||
<div class="-mr-3 inline-block">
|
||||
<PersonCircle class="h-10 w-10 border-2 border-solid border-neutral-900" {pubkey} />
|
||||
</div>
|
||||
{/each}
|
||||
</div>
|
||||
<PersonCircles {pubkeys} />
|
||||
</div>
|
||||
<div class="flex h-12 w-full flex-col overflow-hidden pt-1">
|
||||
<div class="w-full">
|
||||
|
@ -1,9 +1,8 @@
|
||||
<script>
|
||||
import {onMount, onDestroy} from "svelte"
|
||||
import {derived} from "svelte/store"
|
||||
import {partition, assoc} from "ramda"
|
||||
import {filter, assoc} from "ramda"
|
||||
import {now} from "paravel"
|
||||
import {fuzzy, createScroller} from "src/util/misc"
|
||||
import {createScroller} from "src/util/misc"
|
||||
import {giftWrapKinds} from "src/util/nostr"
|
||||
import {getModal} from "src/partials/state"
|
||||
import Anchor from "src/partials/Anchor.svelte"
|
||||
@ -17,27 +16,25 @@
|
||||
deriveIsGroupMember,
|
||||
updateCurrentSession,
|
||||
forcePlatformRelays,
|
||||
session,
|
||||
searchGroups,
|
||||
} from "src/engine"
|
||||
|
||||
const loadMore = async () => {
|
||||
limit += 50
|
||||
limit += 20
|
||||
}
|
||||
|
||||
const scroller = createScroller(loadMore, {element: getModal()})
|
||||
|
||||
const groupList = derived([groups, session], ([$groups, $session]) => {
|
||||
const [joined, other] = partition(g => deriveIsGroupMember(g.address, true).get(), $groups)
|
||||
const userIsMember = g => deriveIsGroupMember(g.address, true).get()
|
||||
|
||||
return {joined, other}
|
||||
})
|
||||
const userGroups = groups.derived(filter(userIsMember))
|
||||
|
||||
let q = ""
|
||||
let limit = 50
|
||||
let limit = 20
|
||||
|
||||
$: searchGroups = fuzzy($groupList.other, {
|
||||
keys: [{name: "id", weight: 0.2}, "meta.name", "meta.description"],
|
||||
})
|
||||
$: otherGroups = $searchGroups(q)
|
||||
.filter(g => !userIsMember(g))
|
||||
.slice(0, limit)
|
||||
|
||||
document.title = "Groups"
|
||||
|
||||
@ -74,7 +71,7 @@
|
||||
<i class="fa-solid fa-plus" /> Create
|
||||
</Anchor>
|
||||
</div>
|
||||
{#each $groupList.joined as group (group.address)}
|
||||
{#each $userGroups as group (group.address)}
|
||||
<GroupListItem address={group.address} />
|
||||
{:else}
|
||||
<p class="text-center py-8">You haven't yet joined any groups.</p>
|
||||
@ -83,6 +80,6 @@
|
||||
<Input bind:value={q} type="text" wrapperClass="flex-grow" placeholder="Search groups">
|
||||
<i slot="before" class="fa-solid fa-search" />
|
||||
</Input>
|
||||
{#each searchGroups(q).slice(0, limit) as group (group.address)}
|
||||
{#each otherGroups as group (group.address)}
|
||||
<GroupListItem address={group.address} />
|
||||
{/each}
|
||||
|
@ -1,11 +1,13 @@
|
||||
import {identity, prop, uniqBy, defaultTo, sortBy, last, whereEq} from "ramda"
|
||||
import {ellipsize, seconds} from "hurdak"
|
||||
import Fuse from "fuse.js"
|
||||
import {identity, prop, uniqBy, map, defaultTo, sortBy, last, whereEq} from "ramda"
|
||||
import {ellipsize, doPipe, seconds} from "hurdak"
|
||||
import {Tags, decodeAddress, addressToNaddr} from "paravel"
|
||||
import {fuzzy} from "src/util/misc"
|
||||
import type {GroupStatus, Session} from "src/engine/session/model"
|
||||
import {pubkey} from "src/engine/session/state"
|
||||
import {session} from "src/engine/session/derived"
|
||||
import {forcePlatformRelays, hints} from "src/engine/relays/utils"
|
||||
import {derivePerson, follows} from "src/engine/people/derived"
|
||||
import {groups, groupSharedKeys, groupAdminKeys} from "./state"
|
||||
import {GroupAccess} from "./model"
|
||||
import type {Group} from "./model"
|
||||
@ -27,7 +29,35 @@ export const deriveGroup = address => {
|
||||
|
||||
export const getGroupSearch = $groups => fuzzy($groups, {keys: ["meta.name", "meta.about"]})
|
||||
|
||||
export const searchGroups = groups.derived(getGroupSearch)
|
||||
export const getWotGroupMembers = address =>
|
||||
Array.from(follows.get()).filter(
|
||||
pk =>
|
||||
derivePerson(pk)
|
||||
.get()
|
||||
.communities?.some(t => t[1] === address),
|
||||
)
|
||||
|
||||
export const searchGroups = groups.throttle(300).derived($groups => {
|
||||
const options = $groups.map(group => ({group, score: getWotGroupMembers(group.address).length}))
|
||||
|
||||
const fuse = new Fuse(options, {
|
||||
keys: [{name: "id", weight: 0.2}, "meta.name", "meta.about"],
|
||||
threshold: 0.3,
|
||||
shouldSort: false,
|
||||
includeScore: true,
|
||||
})
|
||||
|
||||
return (term: string) => {
|
||||
if (!term) {
|
||||
return sortBy(item => -item.score, options).map(item => item.group)
|
||||
}
|
||||
|
||||
return doPipe(fuse.search(term), [
|
||||
sortBy((r: any) => r.score - Math.pow(Math.max(0, r.item.score), 1 / 100)),
|
||||
map((r: any) => r.item.group),
|
||||
])
|
||||
}
|
||||
})
|
||||
|
||||
export const getRecipientKey = wrap => {
|
||||
const pubkey = Tags.fromEvent(wrap).values("p").first()
|
||||
|
@ -30,6 +30,8 @@ export type Person = {
|
||||
mutes?: string[][]
|
||||
relays_updated_at?: number
|
||||
relays?: RelayPolicy[]
|
||||
communities_updated_at?: number
|
||||
communities?: string[][]
|
||||
handle_updated_at?: number
|
||||
handle?: Handle
|
||||
zapper_updated_at?: number
|
||||
|
@ -88,3 +88,9 @@ projections.addHandler(10000, e => {
|
||||
.valueOf(),
|
||||
})
|
||||
})
|
||||
|
||||
projections.addHandler(10004, e => {
|
||||
updateStore(people.key(e.pubkey), e.created_at, {
|
||||
communities: Tags.fromEvent(e).whereKey("a").valueOf(),
|
||||
})
|
||||
})
|
||||
|
@ -25,7 +25,7 @@ export const isKeyValid = (key: string) => {
|
||||
}
|
||||
|
||||
export const noteKinds = [1, 30023, 9802, 1808, 32123, 31923, 30402]
|
||||
export const personKinds = [0, 2, 3, 10000, 10002]
|
||||
export const personKinds = [0, 2, 3, 10000, 10002, 10004]
|
||||
export const reactionKinds = [7, 9735]
|
||||
export const repostKinds = [6, 16]
|
||||
export const giftWrapKinds = [1059, 1060]
|
||||
|
Loading…
Reference in New Issue
Block a user