Skip to content

Commit

Permalink
Merge pull request #125 from NfNitLoop/smipler-nav
Browse files Browse the repository at this point in the history
Integrate "Edit Profile" into the Profile page.
  • Loading branch information
NfNitLoop authored Jul 3, 2023
2 parents 7e625fd + b420c40 commit 59acccd
Show file tree
Hide file tree
Showing 15 changed files with 216 additions and 132 deletions.
26 changes: 1 addition & 25 deletions web-client/components/Button.svelte
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<div class="buttonPosition {$$props.class}">
<div class="button" class:disabled class:confirmationMode on:mouseup={clicked} on:mouseleave={onMouseLeave}>
<div class="button" class:disabled on:mouseup={clicked}>
<slot/>
</div>
</div>
Expand All @@ -19,10 +19,6 @@ export let disabled = false
// Otherwise, we open up a new window (tab) to the new external URL.
export let href = ""
// This button requires confirmation, and is currently asking for confirmation
// TODO: Get rid of confirmation. I think I've stopped using it everywhere. also get rid of buttonPositon container.
let confirmationMode = false
let dispatcher = createEventDispatcher()
function clicked(event: MouseEvent) {
Expand All @@ -42,13 +38,9 @@ function clicked(event: MouseEvent) {
return
}
confirmationMode = false
dispatcher("click")
}
function onMouseLeave() {
confirmationMode = false
}
</script>

Expand Down Expand Up @@ -81,28 +73,12 @@ function onMouseLeave() {
box-shadow: 0px 2px 4px rgba(0, 0, 0, 0.2);
}
.button.confirmationMode {
animation-name: buttonConfirm;
animation-duration: 150ms;
animation-iteration-count: 5;
animation-fill-mode: forwards;
animation-direction: alternate;
animation-timing-function: ease-in-out;
}
/* Required so that we can use position: absolute on the confirmation box. */
.buttonPosition {
position: relative;
}
@keyframes swoopUp {
from {
bottom: 0%;
opacity: 0;
}
}
@keyframes buttonConfirm {
to{
background-color: red;
Expand Down
22 changes: 8 additions & 14 deletions web-client/components/EditProfile.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import type { AppState } from "../ts/app";
import type { Writable } from "svelte/store";
import { UserID as ClientUserID, protobuf as pb, getInner } from "../ts/client";
import { parseUserID, validateServerURL } from "../ts/common";
import { getContext, tick } from "svelte";
import { getContext, onMount, tick } from "svelte";
import InputBox from "./InputBox.svelte";
import { DateTime } from "luxon";
import { decodeBase58 } from "../ts/fbBase58";
Expand All @@ -49,8 +49,6 @@ let appState: Writable<AppState> = getContext("appStateStore")
// Exported so that EditorWithPreview can preview, serialize, & send it for us.
export let item: pb.Item
// Possibly imported, so we can start editing an existing profile:
export let initialItem: pb.Item|undefined
export let validationErrors: string[] = []
$: validationErrors = function(): string[] {
Expand Down Expand Up @@ -164,26 +162,24 @@ $: {
}
}
// This is the inverse of $: itemProto above. Given an Item, load data from it.
// This is the inverse of `$: item = ...` below. Given an Item, load data from it.
function loadFromProto(item: pb.Item) {
let profile = getInner(item, "profile")!
displayName = profile.displayName
profileContent = profile.about
let profile = getInner(item, "profile")
displayName = profile?.displayName ?? ""
profileContent = profile?.about ?? ""
let _follows = new Array<FollowEntry>()
profile.follows.forEach((follow) => {
profile?.follows.forEach((follow) => {
let f = new FollowEntry(ClientUserID.fromBytes(follow.user!.bytes).toString(), follow.displayName)
_follows.push(f)
})
follows = _follows
servers = profile.servers.map((s) => { return {url: s.url} })
servers = profile?.servers.map((s) => { return {url: s.url} }) ?? []
}
if (initialItem) {
loadFromProto(initialItem)
}
loadFromProto(item)
$: item = function(): pb.Item {
Expand Down Expand Up @@ -221,6 +217,4 @@ $: item = function(): pb.Item {
return item
}()
</script>
19 changes: 11 additions & 8 deletions web-client/components/EditorWithPreview.svelte
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
<PageHeading />
{#if !reuse}
<PageHeading />

<TabBar {tabs} bind:activeTab/>
<TabBar {tabs} bind:activeTab/>
{/if}

{#if activeTab == "Edit"}
{#if mode === "profile"}
<EditProfile
{initialItem}
bind:validationErrors
bind:item
bind:this={editProfile}
Expand Down Expand Up @@ -71,12 +72,14 @@ let appState: Writable<AppState> = getContext("appStateStore")
// There will probably be a separate, inline editor for "comment" types since they'll be simpler.
export let mode: "post"|"profile" = "post"
let tabs = ["Edit", "Preview"]
let activeTab = "Edit"
// A hack to let me re-use this w/o tearing out all the logic:
export let reuse = false
// Can provide an initial item for editing.
export let initialItem: pb.Item|undefined = undefined
type TabType = "Edit" | "Preview"
let tabs: TabType[] = ["Edit", "Preview"]
export let activeTab: TabType = "Edit"
// Can provide an initial item for editing.
let fileAttachments: FileInfo[] = []
let userID: ClientUserID
Expand All @@ -89,7 +92,7 @@ let warnings: string[] = []
// The Item protobuf generated by EditProfile/EditPost.
let item: pb.Item = new pb.Item()
export let item: pb.Item = new pb.Item()
let editPost: EditPost|undefined = undefined
let editProfile: EditProfile|undefined = undefined
Expand Down
6 changes: 5 additions & 1 deletion web-client/components/ItemHeader.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,11 @@
<div class="header">
<ProfileImage {userID} />
<div class="text">
<UserIdView {userID} />
{#if profile}
<UserIdView {userID} displayName={profile.displayName} resolve={false} shouldLink={!previewMode}/>
{:else}
<UserIdView {userID} shouldLink={!previewMode} />
{/if}
{#if showReplyTo && comment}
<a href={refToLink(comment.replyTo)}>
replied to
Expand Down
68 changes: 46 additions & 22 deletions web-client/components/ItemView.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import UserIdView from "./UserIDView.svelte"
import CommentView from "./CommentView.svelte"
import ItemHeader from "./ItemHeader.svelte"
import { createEventDispatcher, getContext, tick } from "svelte";
import UserIdChip from "./UserIDChip.svelte";
export let userID: string
export let signature: string
Expand Down Expand Up @@ -223,6 +224,7 @@ function leftPage() {
</div>
</div>
{:else}<!-- item && !loadError-->
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div
class="item"
id={signature}
Expand Down Expand Up @@ -264,37 +266,50 @@ function leftPage() {
{:else if profile}
<ItemHeader item={loadedItem} userID={UserID.fromString(userID)} {signature} {previewMode} bind:viewMode />
<div class="body">
{#if profile.displayName}
<h1>{profile.displayName}</h1>
{/if}
<div class="userIDInfo">
id: <UserIdView userID={UserID.fromString(userID)} resolve={false} shouldLink={false} />
</div>
{#if viewMode == "normal"}
{@html markdownToHtml(profile.about, {relativeBase: `/u/${userID}/i/${signature}`})}
{:else if viewMode == "markdown"}
{#if viewMode == "markdown"}
<p>Markdown source:</p>
<code><pre>{profile.about}</pre></code>
{:else}
{:else if viewMode == "data"}
<p>JSON representation of Protobuf Item:</p>
<code><pre>{JSON.stringify(loadedItem, null, 4)}</pre></code>
{:else}
{@html markdownToHtml(profile.about, {relativeBase: `/u/${userID}/i/${signature}`})}

{#if validFollows.length > 0}
<h2>Follows</h2>
<user-follows>
{#each validFollows as follow}
<UserIdChip
userID={follow.userID}
displayName={follow.displayName}
shouldLink={!previewMode}
/>
{:else}
<div>(None)</div>
{/each}
</user-follows>
{/if}

{#if profile.servers.length > 0}
<h2>Servers</h2>
<ul>
{#each profile.servers as server (server)}
<!-- NOT hyperlinking this for now, in case someone tries to inject a javascript: link. -->
<li><code>{server.url}</code></li>
{:else}
<li>(None)</li>
{/each}
</ul>
{/if}
{/if}

<h2>Follows</h2>
<ul>
{#each validFollows as follow}
<li><UserIdView userID={follow.userID} displayName={follow.displayName} resolve={false}/></li>
{:else}
<li>(None)</li>
{/each}
</ul>

<h2>Servers</h2>
<ul>
{#each profile.servers as server (server)}
<!-- NOT hyperlinking this for now, in case someone tries to inject a javascript: link. -->
<li><code>{server.url}</code></li>
{:else}
<li>(None)</li>
{/each}
</ul>

</div>
{:else if loadedItem.itemType.case == "comment"}
<CommentView {showReplyTo} item={loadedItem}
Expand All @@ -321,6 +336,10 @@ function leftPage() {
color: #888;
}
h1:has(+ .userIDInfo) {
margin-bottom: 0;
}
.shrinkImages .body :global(img) {
height: 5px;
}
Expand All @@ -330,4 +349,9 @@ function leftPage() {
box-shadow: 0px 5px 20px rgb(0 0 0 / 80%);
}
user-follows {
display: flex;
flex-wrap: wrap;
}
</style>
8 changes: 1 addition & 7 deletions web-client/components/PageHeading.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -196,20 +196,14 @@ function setNav(app: AppState) {
isActive: new UrlPattern("/u/:uid/profile").match(pagePath),
})
// TODO: Inline "New Post" and "Edit Profile" into the Post/Profile page.
// TODO: Inline "New Post" into the Post/Profile page.
if (isMe) {
navs.push({
text: `New Post`,
href: `#/u/${uid}/post`,
isActive: new UrlPattern("/u/:uid/post").match(pagePath),
})
navs.push({
text: `Edit Profile`,
href: `#/u/${uid}/profile/edit`,
isActive: new UrlPattern("/u/:uid/profile/edit").match(pagePath),
})
navs.push({
text: `Sync`,
href: `#/u/${uid}/sync`,
Expand Down
15 changes: 13 additions & 2 deletions web-client/components/SignAndSend.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -277,7 +277,14 @@ async function trackerSubmit(tracker: TaskTracker): Promise<void> {
}
// Save this before onSendSuccess(), because it could change values:
let navigateDestination = `#/u/${userID}/i/${sig}/`
const isProfileUpdate = item.itemType.case == "profile"
let navigateDestination =
isProfileUpdate ? `#/u/${userID}/profile`
: `#/u/${userID}/i/${sig}/`
if (isProfileUpdate) {
$appState.userProfileChanged()
}
await tracker.runSubtask("executing onSendSuccess()", async (tracker) => {
// Mostly here to catch and report an exception in the handler:
Expand All @@ -290,7 +297,11 @@ async function trackerSubmit(tracker: TaskTracker): Promise<void> {
}
if (navigateWhenDone) {
window.location.hash = navigateDestination
if (window.location.hash == navigateDestination) {
window.location.reload()
} else {
window.location.hash = navigateDestination
}
}
}
Expand Down
4 changes: 1 addition & 3 deletions web-client/components/TabBar.svelte
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
<!-- a tab bar that sits atop an item. -->
<div class="tabBar" transition:slide|local>
<div class="tabBar">
{#each tabs as tabName, idx (tabName)}
<span class="tab" class:inactive={idx != activeIdx} on:click={() => setActiveIndex(idx)}>{tabName}</span>
{/each}
</div>

<script lang="ts">
import { slide } from "svelte/transition";
export let tabs: string[] = []
Expand Down
36 changes: 36 additions & 0 deletions web-client/components/UserIDChip.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<!--
A "chip" element w/ userID, and their icon.
-->

<user-chip>
<ProfileImage {userID} size="line" />
<UserIDView {userID} {displayName} {href} {shouldLink} />
</user-chip>

<script lang="ts">
import type { UserID } from "feoblog-client";
import UserIDView from "./UserIDView.svelte"
import ProfileImage from "./ProfileImage.svelte";
export let userID: UserID
export let displayName: string = ""
export let href: string|undefined = undefined
export let shouldLink = true
</script>

<style>
user-chip {
display: inline-block;
border-radius: 5px;
/* TODO: Same as others */
background-color: #eee;
padding: 0.25em;
margin: 0.25em;
white-space: nowrap;
max-width: 20em;
text-overflow: ellipsis;
}
</style>
Loading

0 comments on commit 59acccd

Please sign in to comment.