Change deeply the look of the application. Still to do: timelines/collections, activities.
This commit is contained in:
parent
7c0d471328
commit
7e04869453
54
apmail.css
54
apmail.css
|
@ -7,31 +7,19 @@ body {
|
|||
|
||||
color: hsl(240, 10%, 15%);
|
||||
border-color: hsl(240, 10%, 15%);
|
||||
}
|
||||
|
||||
/* Header */
|
||||
header {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: hsl(240, 10%, 75%);
|
||||
border-style: solid;
|
||||
border-width: thin;
|
||||
border-radius: 0.5em;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
text-align: center;
|
||||
margin-bottom: 0.5em;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
|
||||
nav {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: center;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
.page {
|
||||
|
@ -47,7 +35,6 @@ nav {
|
|||
margin: 0;
|
||||
border-style: solid;
|
||||
border-width: thin;
|
||||
border-radius: 0.5em 0.5em 0 0;
|
||||
background-color: hsl(240, 10%, 65%);
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
|
@ -55,6 +42,18 @@ nav {
|
|||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.error {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: hsl(0, 40%, 85%);
|
||||
border-style: solid;
|
||||
border-width: thin;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
/* Main */
|
||||
h1 {
|
||||
padding: 0;
|
||||
|
@ -92,27 +91,26 @@ main {
|
|||
background-color: hsl(240, 10%, 85%);
|
||||
border-style: solid;
|
||||
border-width: thin;
|
||||
border-radius: 0 0.5em 0.5em 0.5em;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
/* Footer */
|
||||
footer {
|
||||
.timeline {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
background-color: hsl(240, 10%, 75%);
|
||||
background-color: hsl(240, 10%, 85%);
|
||||
border-style: solid;
|
||||
border-width: thin;
|
||||
border-radius: 0.5em;
|
||||
padding-top: 0.5em;
|
||||
padding-bottom: 0.5em;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
text-align: center;
|
||||
margin-top: 0.5em;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
align-items: stretch;
|
||||
}
|
||||
|
||||
/* Other */
|
||||
|
@ -146,7 +144,6 @@ li.actor-display {
|
|||
display: inline-block;
|
||||
border-style: solid;
|
||||
border-width: thin;
|
||||
border-radius: 0.5em;
|
||||
padding: 0.1em;
|
||||
margin: 0;
|
||||
margin-left: 0.5em;
|
||||
|
@ -158,7 +155,6 @@ article.activity {
|
|||
display: block;
|
||||
border-style: solid;
|
||||
border-width: thin;
|
||||
border-radius: 0.5em;
|
||||
margin: 0;
|
||||
padding: 0.5em;
|
||||
margin-top: 0.1em;
|
||||
|
@ -192,3 +188,7 @@ section.activity-object-field:after {
|
|||
section.activity-object-content {
|
||||
background-color: hsl(240, 10%, 95%);
|
||||
}
|
||||
|
||||
#profile-display-name {
|
||||
font-size: xx-large;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,102 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
width="96"
|
||||
height="96"
|
||||
viewBox="0 0 25.399999 25.400001"
|
||||
version="1.1"
|
||||
id="svg8"
|
||||
inkscape:version="0.92.4 5da689c313, 2019-01-14"
|
||||
sodipodi:docname="unknown-user.svg">
|
||||
<defs
|
||||
id="defs2">
|
||||
<inkscape:path-effect
|
||||
effect="simplify"
|
||||
id="path-effect821"
|
||||
is_visible="true"
|
||||
steps="1"
|
||||
threshold="0.000408163"
|
||||
smooth_angles="360"
|
||||
helper_size="0"
|
||||
simplify_individual_paths="false"
|
||||
simplify_just_coalesce="false"
|
||||
simplifyindividualpaths="false"
|
||||
simplifyJustCoalesce="false" />
|
||||
<inkscape:path-effect
|
||||
effect="simplify"
|
||||
id="path-effect817"
|
||||
is_visible="true"
|
||||
steps="1"
|
||||
threshold="0.000408163"
|
||||
smooth_angles="360"
|
||||
helper_size="0"
|
||||
simplify_individual_paths="false"
|
||||
simplify_just_coalesce="false"
|
||||
simplifyindividualpaths="false"
|
||||
simplifyJustCoalesce="false" />
|
||||
</defs>
|
||||
<sodipodi:namedview
|
||||
id="base"
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1.0"
|
||||
inkscape:pageopacity="0.0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:zoom="4.8024336"
|
||||
inkscape:cx="44.525706"
|
||||
inkscape:cy="35.984974"
|
||||
inkscape:document-units="px"
|
||||
inkscape:current-layer="layer1"
|
||||
showgrid="false"
|
||||
units="px"
|
||||
inkscape:window-width="1920"
|
||||
inkscape:window-height="1049"
|
||||
inkscape:window-x="0"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="1" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
inkscape:label="Calque 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"
|
||||
transform="translate(0,-271.59998)">
|
||||
<rect
|
||||
style="opacity:1;fill:#ececec;fill-opacity:1;stroke:#000000;stroke-width:0.5291667;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="rect875"
|
||||
width="17.118422"
|
||||
height="17.118422"
|
||||
x="201.45149"
|
||||
y="183.49098"
|
||||
transform="rotate(45)" />
|
||||
<path
|
||||
style="opacity:1;fill:#7b7b7b;fill-opacity:1;stroke:#000000;stroke-width:1.99999988;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
d="M 48 42.277344 A 12.285437 36.856316 0 0 0 35.714844 79.132812 A 12.285437 36.856316 0 0 0 35.742188 81.492188 L 48 93.75 L 60.246094 81.503906 A 12.285437 36.856316 0 0 0 60.285156 79.132812 A 12.285437 36.856316 0 0 0 48 42.277344 z "
|
||||
transform="matrix(0.26458333,0,0,0.26458333,0,271.59998)"
|
||||
id="path879" />
|
||||
<circle
|
||||
style="opacity:1;fill:#7b7b7b;fill-opacity:1;stroke:#000000;stroke-width:0.52916664;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path877"
|
||||
cx="12.7"
|
||||
cy="280.03113"
|
||||
r="3.6361773" />
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 3.5 KiB |
187
index.html
187
index.html
|
@ -8,95 +8,112 @@
|
|||
<script src="render.js"></script>
|
||||
</head>
|
||||
<body onload="UI.checkConnection()">
|
||||
<nav id="tab-bar" style="visibility:hidden;">
|
||||
<!-- Profile page tab -->
|
||||
<input type="radio" id="profile-selector" class="page" name="page" value="profile" checked onchange="UI.showPage('profile')" />
|
||||
<label for="profile-selector" class="page-label" id="profile-selector-label">Profile</label>
|
||||
<nav id="tab-bar">
|
||||
<!-- Send page tab -->
|
||||
<input type="radio" id="send-selector" class="page" name="page" value="send" checked onchange="UI.showPage('send')" />
|
||||
<input type="radio" id="send-selector" class="page" name="page" value="send" checked onchange="UI.setContext('send-message')" />
|
||||
<label for="send-selector" class="page-label" id="send-selector-label">Send Message</label>
|
||||
<!-- Inbox tab -->
|
||||
<input type="radio" id="inbox-selector" class="page" name="page" value="inbox" onchange="UI.showPage('inbox')" />
|
||||
<label for="inbox-selector" class="page-label" id="inbox-selector-label">Inbox</label>
|
||||
<input type="radio" id="inbox-selector" class="page" name="page" value="inbox" onchange="UI.setContext('my-inbox')" />
|
||||
<label for="inbox-selector" class="page-label" id="inbox-selector-label">My Inbox</label>
|
||||
<!-- Outbox tab -->
|
||||
<input type="radio" id="outbox-selector" class="page" name="page" value="outbox" onchange="UI.showPage('outbox')" />
|
||||
<label for="outbox-selector" class="page-label" id="outbox-selector-label">Outbox</label>
|
||||
<!-- Lookup user tab -->
|
||||
<input type="radio" id="lookup-selector" class="page" name="page" value="lookup" onchange="UI.showPage('lookup')" />
|
||||
<label for="lookup-selector" class="page-label" id="lookup-selector-label">Lookup User</label>
|
||||
<!-- Disconnection -->
|
||||
<input type="radio" id="disconnect-selector" class="page" name="page" value="disconnect" onchange="UI.showPage('select-user')" />
|
||||
<label for="disconnect-selector" class="page-label" id="disconnect-selector-label">Disconnection</label>
|
||||
<input type="radio" id="outbox-selector" class="page" name="page" value="outbox" onchange="UI.setContext('my-outbox')" />
|
||||
<label for="outbox-selector" class="page-label" id="outbox-selector-label">My Outbox</label>
|
||||
<!-- Profile -->
|
||||
<input type="radio" id="profile-selector" class="page" name="page" value="profile" onchange="UI.setContext('my-profile')" />
|
||||
<label for="profile-selector" class="page-label" id="profile-selector-label">My Profile</label>
|
||||
<!-- Lookup user box -->
|
||||
<nav class="page-label">
|
||||
<label for="lookup-actor" id="lookup-actor-label">Lookup Actor</label>
|
||||
<input id="lookup-actor" type="text" placeholder="name@server"/>
|
||||
<button onclick="UI.lookupActor()">Search</button>
|
||||
</nav>
|
||||
</nav>
|
||||
<!-- Connection pages -->
|
||||
<main id="select-user">
|
||||
<h2>Connection</h2>
|
||||
Indicate the account to connect to. <br/>
|
||||
<input id="connect-username" type="text" placeholder="user@server" pattern=".*@.*" required /><br/>
|
||||
<button onclick="UI.selectUser()">Next</button>
|
||||
<section id="select-user-error"></section>
|
||||
</main>
|
||||
<main id="ask-password" style="display:none;">
|
||||
<h2>Password</h2>
|
||||
<section id="ask-password-user-info"></section>
|
||||
Enter the password for this account. <br/>
|
||||
<input id="connect-password" type="password" placeholder="password" /><br/>
|
||||
<button onclick="UI.showPage('select-user')">Back</button>
|
||||
<button onclick="UI.connectUser()">Connect</button>
|
||||
<section id="ask-password-error"></section>
|
||||
</main>
|
||||
<!-- Profile page -->
|
||||
<main id="profile" style="display:none;">
|
||||
<section id="profile-info"></section>
|
||||
</main>
|
||||
<!-- Send message page -->
|
||||
<main id="send" style="display:none;">
|
||||
<h4>Audience</h4>
|
||||
<label for="send-message-public-visibility">General visibility</label>
|
||||
<select id="send-message-public-visibility" onchange="UI.updateSendVisibility()">
|
||||
<option value="to">Public (to), displayed in local/global timelines</option>
|
||||
<option value="cc">Public (cc), hidden from local/global timelines</option>
|
||||
<option value="non">Not public</option>
|
||||
</select><br/>
|
||||
<label for="send-message-follower-visibility">Follower's visibility</label>
|
||||
<select id="send-message-follower-visibility" onchange="UI.updateSendVisibility()">
|
||||
<option value="to">Public (to)</option>
|
||||
<option value="cc">Public (cc)</option>
|
||||
<option value="non">Not sent to followers</option>
|
||||
</select><br/>
|
||||
<label for="send-message-to-recipient">To</label>
|
||||
<ul id="send-message-to" class="recipient-list"></ul>
|
||||
<input id="send-message-to-recipient" type="text" placeholder="user@instance" size="40" />
|
||||
<button onclick="UI.addToRecipient()">Add</button><br/>
|
||||
<label for="send-message-cc-recipient">Cc</label>
|
||||
<ul id="send-message-cc" class="recipient-list"></ul>
|
||||
<input id="send-message-cc-recipient" type="text" placeholder="user@instance" size="40" />
|
||||
<button onclick="UI.addCcRecipient()">Add</button><br/>
|
||||
<section id="send-message-recipient-error"></section>
|
||||
<hr/>
|
||||
<h4>Message</h4>
|
||||
<input id="send-message-subject" type="text" onchange="UI.updateSendContent()" size="80" placeholder="Subject (optional)"/> <br/>
|
||||
<textarea id="send-message-content" rows="20" cols="80" placeholder="What do you want to say ?" onchange="UI.updateSendContent()"></textarea> <br/>
|
||||
<button onclick="UI.sendMessage()">Send</button>
|
||||
<section id="send-error"></section>
|
||||
</main>
|
||||
<!-- Inbox page -->
|
||||
<main id="inbox" style="display:none;">
|
||||
<section id="inbox-messages"></section>
|
||||
<section id="inbox-messages-error"></section>
|
||||
</main>
|
||||
<!-- Outbox page -->
|
||||
<main id="outbox" style="display:none;">
|
||||
<section id="outbox-messages"></section>
|
||||
<section id="outbox-messages-error"></section>
|
||||
</main>
|
||||
<!-- Lookup page -->
|
||||
<main id="lookup" style="display:none;">
|
||||
<input id="lookup-user" type="text" placeholder="user@instance"/> <button onclick="UI.lookupUser()">Lookup user</button> <br/><hr/>
|
||||
<section id="lookup-user-error"></section>
|
||||
<section id="lookup-user-info"></section><hr/>
|
||||
<section id="lookup-user-timeline"></section>
|
||||
<section id="lookup-user-timeline-error"></section>
|
||||
</main>
|
||||
<!-- Timelines -->
|
||||
<section id="timeline" style="display:none;">
|
||||
<section id="timeline-error" class="error"></section>
|
||||
<section id="timeline-data" class="timeline"></section>
|
||||
</section>
|
||||
<!-- Content pages -->
|
||||
<section id="main-content">
|
||||
<section id="content-error" class="error"></section>
|
||||
<!-- Account selection page -->
|
||||
<main id="select-user" style="display:none;">
|
||||
<h2>Connection</h2>
|
||||
Indicate the account to connect to. <br/>
|
||||
<input id="connect-username" type="text" placeholder="name@server" pattern=".*@.*" required /><br/>
|
||||
<button onclick="UI.selectUser()">Next</button>
|
||||
</main>
|
||||
<!-- Password page -->
|
||||
<main id="ask-password" style="display:none;">
|
||||
<h2>Password</h2>
|
||||
<section id="ask-password-user-info">
|
||||
<section class="actor-display">
|
||||
<span id="ask-password-user-icon"/></span>
|
||||
<p style="display:inline-block;">
|
||||
<strong><span id="ask-password-user-display-name"></span></strong><br/>
|
||||
<a id="ask-password-user-address"></a>
|
||||
</p>
|
||||
</section>
|
||||
</section>
|
||||
Enter the password for this account. <br/>
|
||||
<input id="connect-password" type="password" placeholder="password" /><br/>
|
||||
<button onclick="UI.showPage('select-user', undefined)">Back</button>
|
||||
<button onclick="UI.connectUser()">Connect</button>
|
||||
</main>
|
||||
<!-- Profile page -->
|
||||
<main id="show-profile" style="display:none;">
|
||||
<section>
|
||||
<span id="profile-icon"></span>
|
||||
<p style="display:inline-block;">
|
||||
<span id="profile-display-name"></span><br/>
|
||||
<a id="profile-address"></a>
|
||||
</p>
|
||||
</section>
|
||||
<section>
|
||||
<p id="profile-summary">
|
||||
</p>
|
||||
</section>
|
||||
<section>
|
||||
<details>
|
||||
<summary>Show source</summary>
|
||||
<textarea rows="30" cols="120" readonly id="profile-code-source">
|
||||
</textarea>
|
||||
</details>
|
||||
</section>
|
||||
</main>
|
||||
<!-- Show Message page -->
|
||||
<main id="show-message" style="display:none;">
|
||||
<section id="message-info"></section>
|
||||
</main>
|
||||
<!-- Send message page -->
|
||||
<main id="send-message" style="display:none;">
|
||||
<h4>Audience</h4>
|
||||
<label for="send-message-public-visibility">General visibility</label>
|
||||
<select id="send-message-public-visibility" onchange="UI.updateSendVisibility()">
|
||||
<option value="to">Public (to), displayed in local/global timelines</option>
|
||||
<option value="cc">Public (cc), hidden from local/global timelines</option>
|
||||
<option value="non">Not public</option>
|
||||
</select><br/>
|
||||
<label for="send-message-follower-visibility">Follower's visibility</label>
|
||||
<select id="send-message-follower-visibility" onchange="UI.updateSendVisibility()">
|
||||
<option value="to">Public (to)</option>
|
||||
<option value="cc">Public (cc)</option>
|
||||
<option value="non">Not sent to followers</option>
|
||||
</select><br/>
|
||||
<label for="send-message-to-recipient">To</label>
|
||||
<ul id="send-message-to" class="recipient-list"></ul>
|
||||
<input id="send-message-to-recipient" type="text" placeholder="user@instance" size="40" />
|
||||
<button onclick="UI.addToRecipient()">Add</button><br/>
|
||||
<label for="send-message-cc-recipient">Cc</label>
|
||||
<ul id="send-message-cc" class="recipient-list"></ul>
|
||||
<input id="send-message-cc-recipient" type="text" placeholder="user@instance" size="40" />
|
||||
<button onclick="UI.addCcRecipient()">Add</button><br/>
|
||||
<section id="send-message-recipient-error"></section>
|
||||
<h4>Message</h4>
|
||||
<input id="send-message-subject" type="text" onchange="UI.updateSendContent()" size="80" placeholder="Subject (optional)"/> <br/>
|
||||
<textarea id="send-message-content" rows="20" cols="80" placeholder="What do you want to say ?" onchange="UI.updateSendContent()"></textarea> <br/>
|
||||
<button onclick="UI.sendMessage()">Send</button>
|
||||
</main>
|
||||
</section>
|
||||
</body>
|
||||
</html>
|
||||
|
|
423
render.js
423
render.js
|
@ -4,211 +4,337 @@ const {Message} = require('./src/message.js')
|
|||
const {ConnectedUser} = require('./src/connected-user.js')
|
||||
|
||||
// For access of elements
|
||||
var Elem = function(id) {
|
||||
const Elem = function(id) {
|
||||
return window.document.getElementById(id)
|
||||
}
|
||||
|
||||
// UI actions
|
||||
var UI = {
|
||||
// Attributes
|
||||
composed_message: new Message(),
|
||||
// Methods
|
||||
// Actor display
|
||||
renderActorTag: function(actor) {
|
||||
// Icon list
|
||||
const Icons = {
|
||||
'unknown-user': "/img/unknown-user.svg"
|
||||
}
|
||||
|
||||
// To render elements that cannot be present in index.html from a model element
|
||||
const Render = {
|
||||
// Render an actor in audience fields context
|
||||
audienceActor: function(actor) {
|
||||
var display = '<section class="actor-display">'
|
||||
if (actor.valid) {
|
||||
if (actor.info.icon) {
|
||||
display = display + '<img src="' + actor.info.icon + '" width="32" height="32" /> '
|
||||
var icon = actor.info.icon
|
||||
if (!icon) {
|
||||
icon = Icons['unknown-user']
|
||||
}
|
||||
display = display
|
||||
+ '<p style="display:inline-block;"><strong>' + actor.displayName() + '</strong> <br/>'
|
||||
+ '<a href="' + actor.urls.profile + '">'
|
||||
+ actor.address()
|
||||
+ '</a></p>'
|
||||
display = display + '<img src="' + actor.info.icon + '" width="32" height="32" /> '
|
||||
+ '<p style="display:inline-block;"><strong>' + actor.displayName() + '</strong> <br/>'
|
||||
+ '<a href="' + actor.urls.profile + '">'
|
||||
+ actor.address()
|
||||
+ '</a></p>'
|
||||
} else {
|
||||
display = display
|
||||
+ '<p style="display:inline-block;">'
|
||||
+ '<a href="' + actor.urls.profile + '">'
|
||||
+ 'Other actor'
|
||||
+ '</a></p>'
|
||||
display = display + '<img src="' + Icons['unknown-user'] + '" width="32" height="32" /> '
|
||||
+ '<p style="display:inline-block;">'
|
||||
+ '<a href="' + actor.urls.profile + '">'
|
||||
+ 'Other actor'
|
||||
+ '</a></p>'
|
||||
}
|
||||
display = display + '</section>'
|
||||
return display
|
||||
},
|
||||
// Show the page tab
|
||||
showPageTab: function(is_shown) {
|
||||
Elem('tab-bar').style.visibility = is_shown ? 'visible' : 'hidden'
|
||||
},
|
||||
// Action done when refreshing a page
|
||||
refreshPage: {
|
||||
'select-user': function() {
|
||||
UI.showPageTab(false)
|
||||
ConnectedUser.disconnect()
|
||||
Elem('connect-username').value = ''
|
||||
// Raw data conversion
|
||||
rawData: function(rawData) {
|
||||
var str_data = JSON.stringify(rawData, null, 1)
|
||||
var replace_map = {
|
||||
'&': '&',
|
||||
'<': '<',
|
||||
'>': '>',
|
||||
'"': '"',
|
||||
'\'': '''
|
||||
}
|
||||
str_data = str_data.replace(/[&<>"']/g, x => replace_map[x])
|
||||
return str_data
|
||||
}
|
||||
}
|
||||
|
||||
// UI actions
|
||||
const UI = {
|
||||
// Attributes
|
||||
composed_message: new Message(), // Message used in composition page
|
||||
current_context: 'my-inbox', // By default, show the inbox
|
||||
is_connected: false, // Indicate if the user is connected
|
||||
other_actor: new Actor(), // Other actor to display
|
||||
// Contextual methods
|
||||
refresh_context: {
|
||||
'send-message': function() {
|
||||
UI.updateNav('send-selector')
|
||||
UI.showTimeline(undefined, undefined)
|
||||
if (UI.is_connected) {
|
||||
UI.showPage('send-message', undefined)
|
||||
} else {
|
||||
UI.showPage('select-user', undefined)
|
||||
}
|
||||
},
|
||||
'ask-password': function() {
|
||||
UI.showPageTab(false)
|
||||
Elem('connect-password').value = ''
|
||||
Elem('ask-password-user-info').innerHTML = UI.renderActorTag(ConnectedUser.actor)
|
||||
'my-inbox': function() {
|
||||
UI.updateNav('inbox-selector')
|
||||
if (UI.is_connected) {
|
||||
UI.showTimeline(ConnectedUser.actor.urls.inbox, ConnectedUser.tokens.user.access_token)
|
||||
UI.showPage('show-profile', ConnectedUser.actor)
|
||||
} else {
|
||||
UI.showTimeline(undefined, undefined)
|
||||
UI.showPage('select-user', undefined)
|
||||
}
|
||||
},
|
||||
'profile': function() {
|
||||
UI.showPageTab(true)
|
||||
UI.updateProfilePage()
|
||||
'my-outbox': function() {
|
||||
UI.updateNav('outbox-selector')
|
||||
if (UI.is_connected) {
|
||||
UI.showTimeline(ConnectedUser.actor.urls.inbox, ConnectedUser.tokens.user.access_token)
|
||||
UI.showPage('show-profile', ConnectedUser.actor)
|
||||
} else {
|
||||
UI.showTimeline(undefined, undefined)
|
||||
UI.showPage('select-user', undefined)
|
||||
}
|
||||
},
|
||||
'send': function() {
|
||||
UI.showPageTab(true)
|
||||
UI.composed_message = new Message()
|
||||
UI.updateSendMessagePage()
|
||||
'my-profile': function() {
|
||||
UI.updateNav('profile-selector')
|
||||
UI.showTimeline(undefined, undefined)
|
||||
if (UI.is_connected) {
|
||||
UI.showPage('show-profile', ConnectedUser.actor)
|
||||
} else {
|
||||
UI.showPage('select-user', undefined)
|
||||
}
|
||||
},
|
||||
'inbox': function() {
|
||||
UI.showPageTab(true)
|
||||
Elem('inbox-messages-error').innerHTML = ''
|
||||
Elem('inbox-messages').innerHTML = 'Loading inbox...'
|
||||
UI.showTimeline('inbox-messages', ConnectedUser.tokens.user.access_token, ConnectedUser.actor.urls.inbox)
|
||||
},
|
||||
'outbox': function() {
|
||||
UI.showPageTab(true)
|
||||
Elem('outbox-messages-error').innerHTML = ''
|
||||
Elem('outbox-messages').innerHTML = 'Loading outbox...'
|
||||
UI.showTimeline('outbox-messages', ConnectedUser.tokens.user.access_token, ConnectedUser.actor.urls.outbox)
|
||||
},
|
||||
'lookup': function() {
|
||||
UI.showPageTab(true)
|
||||
Elem('lookup-user-error').innerHTML = ''
|
||||
Elem('lookup-user-info').innerHTML = ''
|
||||
Elem('lookup-user-timeline').innerHTML = ''
|
||||
Elem('lookup-user-timeline-error').innerHTML = ''
|
||||
'other-profile': function() {
|
||||
UI.updateNav(undefined)
|
||||
if (UI.other_actor.urls.outbox) {
|
||||
UI.showTimeline(UI.other_actor.urls.outbox, undefined)
|
||||
} else {
|
||||
UI.displayTimelineError('Actor does not have a public outbox.')
|
||||
}
|
||||
UI.showPage('show-profile', UI.other_actor)
|
||||
}
|
||||
},
|
||||
// Show a given page
|
||||
showPage: function(page) {
|
||||
['select-user', 'ask-password', 'profile', 'send', 'inbox', 'outbox', 'lookup'].map(x => Elem(x).style.display = 'none')
|
||||
Elem(page).style.display = 'block'
|
||||
UI.refreshPage[page]()
|
||||
// Page refresh methods
|
||||
refresh_page: {
|
||||
'select-user': function(_) {
|
||||
Elem('connect-username').value = ''
|
||||
},
|
||||
'ask-password': function(_) {
|
||||
Elem('connect-password').value = ''
|
||||
var icon = ConnectedUser.actor.info.icon
|
||||
if (!icon) {
|
||||
icon = Icons['unknown-user']
|
||||
}
|
||||
Elem('ask-password-user-icon').innerHTML = '<img src="' + icon + '" width="32" height="32" />'
|
||||
Elem('ask-password-user-display-name').innerText = ConnectedUser.actor.displayName()
|
||||
Elem('ask-password-user-address').href = ConnectedUser.actor.urls.profile
|
||||
Elem('ask-password-user-address').innerText = ConnectedUser.actor.address()
|
||||
},
|
||||
'show-profile': function(actor) {
|
||||
// data contains the actor to display
|
||||
var icon = actor.info.icon
|
||||
if (!icon) {
|
||||
icon = Icons['unknown-user']
|
||||
}
|
||||
Elem('profile-icon').innerHTML = '<img src="' + icon + '" width="96" height="96" />'
|
||||
Elem('profile-display-name').innerText = actor.displayName()
|
||||
Elem('profile-address').href = actor.urls.profile
|
||||
Elem('profile-address').innerText = actor.address()
|
||||
Elem('profile-summary').innerHTML = actor.info.summary
|
||||
Elem('profile-code-source').value = JSON.stringify(actor.raw, null, 1)
|
||||
},
|
||||
'show-message': function(data) {
|
||||
},
|
||||
'send-message': function(_) {
|
||||
Elem('send-message-to-recipient').value = ''
|
||||
Elem('send-message-cc-recipient').value = ''
|
||||
Elem('send-message-public-visibility').value = UI.composed_message.public_visibility
|
||||
Elem('send-message-follower-visibility').value = UI.composed_message.follower_visibility
|
||||
Elem('send-message-subject').value = UI.composed_message.subject
|
||||
Elem('send-message-content').value = UI.composed_message.content
|
||||
// TO/CC
|
||||
Elem('send-message-to').innerHTML = UI.composed_message.to.map(
|
||||
function(element) {
|
||||
return '<li class="actor-display">' + Render.audienceActor(element) + ' <button onclick="UI.removeToRecipient(\'' + element.urls.profile + '\')">×</button></li>'
|
||||
}).join('')
|
||||
Elem('send-message-cc').innerHTML = UI.composed_message.cc.map(
|
||||
function(element) {
|
||||
return '<li class="actor-display">' + Render.audienceActor(element) + ' <button onclick="UI.removeCcRecipient(\'' + element.urls.profile + '\')">×</button></li>'
|
||||
}).join('')
|
||||
}
|
||||
},
|
||||
// When the page loads, load the connected user if already connected
|
||||
// Methods
|
||||
// On load, auto-connect
|
||||
checkConnection: function() {
|
||||
// Connect
|
||||
ConnectedUser.loadFromLocalStorage(
|
||||
function(load_ok, failure_message) {
|
||||
if (load_ok) {
|
||||
// TODO: Refresh the access token ?
|
||||
// No need to show the login pages, go directly to send message page
|
||||
UI.showPage('send')
|
||||
} else {
|
||||
// Show the select user page
|
||||
UI.showPage('select-user')
|
||||
UI.onConnectionChange(load_ok)
|
||||
if (failure_message) {
|
||||
UI.displayContentError(failure_message)
|
||||
}
|
||||
})
|
||||
},
|
||||
// When the user enter its address, load the actor representing the user
|
||||
// On connected, show the right page
|
||||
onConnectionChange: function(connected) {
|
||||
UI.is_connected = connected
|
||||
UI.refresh_context[UI.current_context]()
|
||||
},
|
||||
// Display content errors
|
||||
displayContentError: function(message) {
|
||||
Elem('content-error').style.display = 'block'
|
||||
Elem('content-error').innerText = 'Error: ' + message
|
||||
},
|
||||
// Display timeline errors
|
||||
displayTimelineError: function(message) {
|
||||
Elem('timeline-error').style.display = 'block'
|
||||
Elem('timeline-error').innerText = 'Error: ' + message
|
||||
},
|
||||
// Clear error messages
|
||||
clearError: function() {
|
||||
Elem('content-error').style.display = 'none'
|
||||
Elem('content-error').innerText = ''
|
||||
Elem('timeline-error').style.display = 'none'
|
||||
Elem('timeline-error').innerText = ''
|
||||
},
|
||||
// Show a page
|
||||
showPage: function(page, data) {
|
||||
// Clear errors
|
||||
UI.clearError()
|
||||
// Hide all other pages
|
||||
for (const p in UI.refresh_page) {
|
||||
Elem(p).style.display = 'none'
|
||||
}
|
||||
// Show the page
|
||||
Elem(page).style.display = 'block'
|
||||
// Refresh
|
||||
UI.refresh_page[page](data)
|
||||
},
|
||||
// Show the timeline
|
||||
showTimeline: function(url, token) {
|
||||
if (url) {
|
||||
Elem('timeline').style.display = 'block'
|
||||
Elem('timeline-data').innerHTML = 'Loading collection...'
|
||||
// TODO
|
||||
} else {
|
||||
Elem('timeline').style.display = 'none'
|
||||
}
|
||||
},
|
||||
// Update the nav
|
||||
updateNav: function(selected) {
|
||||
// Unselect all options
|
||||
['send-selector', 'inbox-selector', 'outbox-selector', 'profile-selector'].map(x => Elem(x).checked = false)
|
||||
if (selected) {
|
||||
Elem(selected).checked = true
|
||||
}
|
||||
},
|
||||
// Change context
|
||||
setContext: function(ctx) {
|
||||
UI.current_context = ctx
|
||||
UI.refresh_context[UI.current_context]()
|
||||
},
|
||||
// Lookup actor
|
||||
lookupActor: function() {
|
||||
// Find the actor and change to the 'other-profile' context
|
||||
UI.other_actor = new Actor()
|
||||
UI.other_actor.loadFromNameServerAddress(
|
||||
Elem('lookup-actor').value,
|
||||
function(load_ok, failure_message) {
|
||||
if (load_ok) {
|
||||
UI.setContext('other-profile')
|
||||
} else {
|
||||
UI.displayContentError('Unable to find user (' + failure_message + ')')
|
||||
}
|
||||
})
|
||||
},
|
||||
// Action on the select-user page
|
||||
selectUser: function() {
|
||||
// Load the actor and go to the ask-password page
|
||||
ConnectedUser.actor.loadFromNameServerAddress(
|
||||
Elem('connect-username').value,
|
||||
function(load_ok, failure_message) {
|
||||
if (load_ok) {
|
||||
UI.showPage('ask-password')
|
||||
UI.showPage('ask-password', undefined)
|
||||
} else {
|
||||
Elem('select-user-error').innerText = 'Error: ' + failure_message
|
||||
UI.displayContentError(failure_message)
|
||||
}
|
||||
})
|
||||
},
|
||||
// When the user enter its password, get the access tokens and then go to the send page
|
||||
// Action on the ask-password page
|
||||
connectUser: function() {
|
||||
// Connect the user and go to the send page
|
||||
// Connect the user
|
||||
ConnectedUser.connect(
|
||||
Elem('connect-password').value,
|
||||
function(load_ok, failure_message) {
|
||||
if (load_ok) {
|
||||
UI.showPage('send')
|
||||
} else {
|
||||
Elem('ask-password-error').innerText = 'Error: ' + failure_message
|
||||
UI.onConnectionChange(load_ok)
|
||||
if (failure_message) {
|
||||
UI.displayContentError(failure_message)
|
||||
}
|
||||
})
|
||||
},
|
||||
updateProfilePage: function() {
|
||||
Elem('profile-info').innerHTML = UI.renderActor(ConnectedUser.actor)
|
||||
},
|
||||
updateSendMessagePage: function() {
|
||||
Elem('send-message-to-recipient').value = ''
|
||||
Elem('send-message-cc-recipient').value = ''
|
||||
Elem('send-message-public-visibility').value = UI.composed_message.public_visibility
|
||||
Elem('send-message-follower-visibility').value = UI.composed_message.follower_visibility
|
||||
Elem('send-message-subject').value = UI.composed_message.subject
|
||||
Elem('send-message-content').value = UI.composed_message.content
|
||||
// TO/CC
|
||||
Elem('send-message-to').innerHTML = UI.composed_message.to.map(
|
||||
function(element) {
|
||||
return '<li class="actor-display">' + UI.renderActorTag(element) + ' <button onclick="UI.removeToRecipient(\'' + element.urls.profile + '\')">×</button></li>'
|
||||
}).join('')
|
||||
Elem('send-message-cc').innerHTML = UI.composed_message.cc.map(
|
||||
function(element) {
|
||||
return '<li class="actor-display">' + UI.renderActorTag(element) + ' <button onclick="UI.removeCcRecipient(\'' + element.urls.profile + '\')">×</button></li>'
|
||||
}).join('')
|
||||
// Errors
|
||||
Elem('send-message-recipient-error').innerHTML = ''
|
||||
Elem('send-error').innerHTML = ''
|
||||
},
|
||||
// Action on the send page
|
||||
// Update visibility
|
||||
updateSendVisibility: function() {
|
||||
UI.composed_message.setVisibility(Elem('send-message-public-visibility').value, Elem('send-message-follower-visibility').value)
|
||||
},
|
||||
updateSendContent: function() {
|
||||
UI.composed_message.setContent(Elem('send-message-subject').value, Elem('send-message-content').value)
|
||||
},
|
||||
// Add to recipient lists
|
||||
// Add in To
|
||||
addToRecipient: function() {
|
||||
var actor = new Actor()
|
||||
const actor = new Actor()
|
||||
actor.loadFromNameServerAddress(
|
||||
Elem('send-message-to-recipient').value,
|
||||
function(load_ok, failure_message) {
|
||||
if (load_ok) {
|
||||
UI.composed_message.addToRecipient(actor)
|
||||
UI.updateSendMessagePage()
|
||||
UI.showPage('send-message', undefined)
|
||||
} else {
|
||||
Elem('send-message-recipient-error').innerHTML = 'Unable to find user (' + failure_message + ')'
|
||||
UI.displayContentError('Unable to find user (' + failure_message + ')')
|
||||
}
|
||||
})
|
||||
},
|
||||
// Add in Cc
|
||||
addCcRecipient: function() {
|
||||
var actor = new Actor()
|
||||
const actor = new Actor()
|
||||
actor.loadFromNameServerAddress(
|
||||
Elem('send-message-cc-recipient').value,
|
||||
Elem('send-message-to-recipient').value,
|
||||
function(load_ok, failure_message) {
|
||||
if (load_ok) {
|
||||
UI.composed_message.addCcRecipient(actor)
|
||||
UI.updateSendMessagePage()
|
||||
UI.showPage('send-message', undefined)
|
||||
} else {
|
||||
Elem('send-message-recipient-error').innerHTML = 'Unable to find user (' + failure_message + ')'
|
||||
UI.displayContentError('Unable to find user (' + failure_message + ')')
|
||||
}
|
||||
})
|
||||
},
|
||||
// Remove from recipient lists
|
||||
// Remove from To
|
||||
removeToRecipient: function(url_profile) {
|
||||
// Don't fetch the actor, only set the profile url used in removal
|
||||
var actor = new Actor()
|
||||
const actor = new Actor()
|
||||
actor.urls.profile = url_profile
|
||||
//
|
||||
UI.composed_message.removeToRecipient(actor)
|
||||
UI.updateSendMessagePage()
|
||||
UI.showPage('send-message', undefined)
|
||||
},
|
||||
// Remove from Cc
|
||||
removeCcRecipient: function(url_profile) {
|
||||
var actor = new Actor()
|
||||
// Don't fetch the actor, only set the profile url used in removal
|
||||
const actor = new Actor()
|
||||
actor.urls.profile = url_profile
|
||||
//
|
||||
UI.composed_message.removeCcRecipient(actor)
|
||||
UI.updateSendMessagePage()
|
||||
UI.showPage('send-message', undefined)
|
||||
},
|
||||
// Update message content
|
||||
updateSendContent: function() {
|
||||
UI.composed_message.setContent(Elem('send-message-subject').value, Elem('send-message-content').value)
|
||||
},
|
||||
// Send message
|
||||
sendMessage: function() {
|
||||
UI.composed_message.send(
|
||||
function(is_ok, failure_message) {
|
||||
if (is_ok) {
|
||||
UI.showPage('send')
|
||||
UI.showPage('send-message', undefined)
|
||||
} else {
|
||||
Elem('send-error').innerText = failure_message
|
||||
UI.displayContentError('Error when sending message: ' + failure_message)
|
||||
}
|
||||
})
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
renderRawData: function(rawData) {
|
||||
var str_data = JSON.stringify(rawData, null, 1)
|
||||
var replace_map = {
|
||||
|
@ -300,51 +426,6 @@ var UI = {
|
|||
Elem(id + '-error').innerText = failure_message
|
||||
}
|
||||
})
|
||||
},
|
||||
renderActor: function(actor) {
|
||||
var display = '<section>'
|
||||
if (actor.valid) {
|
||||
if (actor.info.icon) {
|
||||
display = display + '<img src="' + actor.info.icon + '" width="96" height="96" /> '
|
||||
}
|
||||
display = display
|
||||
+ '<p style="display:inline-block;"><strong>' + actor.displayName() + '</strong> <br/>'
|
||||
+ '<a href="' + actor.urls.profile + '">'
|
||||
+ actor.address()
|
||||
+ '</a></p>'
|
||||
+ '<p>' + actor.info.summary + '</p>'
|
||||
} else {
|
||||
display = display
|
||||
+ '<p style="display:inline-block;">'
|
||||
+ '<a href="' + actor.urls.profile + '">'
|
||||
+ 'Other actor'
|
||||
+ '</a></p>'
|
||||
}
|
||||
display = display + '</section>'
|
||||
if (actor.raw) {
|
||||
display = display + UI.renderRawData(actor.raw)
|
||||
}
|
||||
return display
|
||||
},
|
||||
lookupUser: function() {
|
||||
Elem('lookup-user-info').innerHTML = ''
|
||||
Elem('lookup-user-timeline').innerHTML = ''
|
||||
Elem('lookup-user-error').innerHTML = ''
|
||||
Elem('lookup-user-timeline-error').innerHTML = ''
|
||||
var actor = new Actor()
|
||||
actor.loadFromNameServerAddress(
|
||||
Elem('lookup-user').value,
|
||||
function(load_ok, failure_message) {
|
||||
if (load_ok) {
|
||||
Elem('lookup-user-info').innerHTML = UI.renderActor(actor)
|
||||
if (actor.urls.outbox) {
|
||||
UI.showTimeline('lookup-user-timeline', undefined, actor.urls.outbox)
|
||||
} else {
|
||||
Elem('lookup-user-timeline-error').innerText = 'User does not have a public outbox.'
|
||||
}
|
||||
} else {
|
||||
Elem('lookup-user-error').innerText = 'Unable to find user (' + failure_message + ')'
|
||||
}
|
||||
})
|
||||
}
|
||||
*/
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue