Api and UI updates
This commit is contained in:
parent
dee3883537
commit
0ec5864e54
|
@ -22,7 +22,25 @@ var TransSchemas = {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var ApiSchema = {
|
var ApiSchema = {
|
||||||
__Account__: {
|
Note: { // TODO: Figure out renotes
|
||||||
|
Content: {
|
||||||
|
Mastodon: "content",
|
||||||
|
Misskey: "text",
|
||||||
|
},
|
||||||
|
Profile: {
|
||||||
|
Mastodon: "account",
|
||||||
|
Misskey: "user",
|
||||||
|
},
|
||||||
|
Time: {
|
||||||
|
Mastodon: "created_at",
|
||||||
|
Misskey: "createdAt",
|
||||||
|
},
|
||||||
|
Url: {
|
||||||
|
Mastodon: "url",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
Profile: {
|
||||||
|
Avatar: {}, // would "Character" be better?
|
||||||
Banner: {
|
Banner: {
|
||||||
Mastodon: "header",
|
Mastodon: "header",
|
||||||
Misskey: "bannerUrl",
|
Misskey: "bannerUrl",
|
||||||
|
@ -39,36 +57,18 @@ var ApiSchema = {
|
||||||
Mastodon: "display_name",
|
Mastodon: "display_name",
|
||||||
Misskey: "name",
|
Misskey: "name",
|
||||||
},
|
},
|
||||||
Url: {
|
Type: {}, // user, bot, channel, group
|
||||||
Mastodon: "url",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Note: {
|
|
||||||
Author: {
|
|
||||||
Mastodon: "account",
|
|
||||||
Misskey: "user",
|
|
||||||
},
|
|
||||||
Content: {
|
|
||||||
Mastodon: "content",
|
|
||||||
Misskey: "text",
|
|
||||||
},
|
|
||||||
Time: {
|
|
||||||
Mastodon: "created_at",
|
|
||||||
Misskey: "createdAt",
|
|
||||||
},
|
|
||||||
Url: {
|
Url: {
|
||||||
Mastodon: "url",
|
Mastodon: "url",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
ApiSchema.Author = CopyObj(ApiSchema.__Account__);
|
|
||||||
ApiSchema.Channel = CopyObj(ApiSchema.__Account__);
|
|
||||||
|
|
||||||
var TransParsers = {
|
var TransParsers = {
|
||||||
Mastodon: {
|
Mastodon: {
|
||||||
Account(Data) {
|
Account(Data) {
|
||||||
//return JsonTransformA(Data, TransSchemas.Mastodon.Author, TransSchemas.Mastodon);
|
//return JsonTransformA(Data, TransSchemas.Mastodon.Author, TransSchemas.Mastodon);
|
||||||
return JsonTransformB(Data, ApiSchema, ApiSchema.Author, 'Mastodon');
|
return JsonTransformB(Data, ApiSchema, ApiSchema.Profile, 'Mastodon');
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
Instance(Data) {
|
Instance(Data) {
|
||||||
|
|
|
@ -34,7 +34,8 @@ var UseFakeApi = true;
|
||||||
-->
|
-->
|
||||||
</div>
|
</div>
|
||||||
<div id="Bottom">
|
<div id="Bottom">
|
||||||
<a href="https://gitlab.com/octtspacc/Friendiiverse">Source Code</a>
|
<a href="javascript:void(0);" onclick="Root.lastChild.remove();">↩️ Back</a>
|
||||||
|
<a href="https://gitlab.com/octtspacc/Friendiiverse">📜️ Source Code</a>
|
||||||
</div>
|
</div>
|
||||||
<script>NoscriptView.remove();</script>
|
<script>NoscriptView.remove();</script>
|
||||||
<script src="./Utils.js"></script>
|
<script src="./Utils.js"></script>
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
var CurrTasks = {};
|
var Tasker = {};
|
||||||
|
var ApiCache = {Notes: {}, Profiles: {},};
|
||||||
|
|
||||||
function DoAsync(First, Then, Data) {
|
function DoAsync(First, Then, Data) {
|
||||||
var Job = RndId();
|
var Job = RndId();
|
||||||
CurrTasks[Job] = {
|
Tasker[Job] = {
|
||||||
Remains: 0,
|
Remains: 0,
|
||||||
Return(Data) {
|
Return(Data) {
|
||||||
this.Remains -= 1;
|
this.Remains -= 1;
|
||||||
|
@ -13,20 +14,20 @@ function DoAsync(First, Then, Data) {
|
||||||
ForceList(First).forEach(function(Fun, Data){
|
ForceList(First).forEach(function(Fun, Data){
|
||||||
var Task = RndId();
|
var Task = RndId();
|
||||||
var Proc = [Job, Task];
|
var Proc = [Job, Task];
|
||||||
CurrTasks[Job][Task] = {};
|
Tasker[Job][Task] = {};
|
||||||
CurrTasks[Job].Remains += 1;
|
Tasker[Job].Remains += 1;
|
||||||
//Fun(Proc, Data);
|
//Fun(Proc, Data);
|
||||||
Data ? Fun(Data, Proc) : Fun(Proc);
|
Data ? Fun(Data, Proc) : Fun(Proc);
|
||||||
});
|
});
|
||||||
// Continuosly check when First functs completed
|
// Continuosly check when First functs completed
|
||||||
CurrTasks[Job].Interval = setInterval(function(Job, Then){
|
Tasker[Job].Interval = setInterval(function(Job, Then){
|
||||||
if (CurrTasks[Job].Remains <= 0) {
|
if (Tasker[Job].Remains <= 0) {
|
||||||
clearInterval(CurrTasks[Job].Interval);
|
clearInterval(Tasker[Job].Interval);
|
||||||
// Call all Then functs
|
// Call all Then functs
|
||||||
ForceList(Then).forEach(function(Fun){
|
ForceList(Then).forEach(function(Fun){
|
||||||
Fun(CurrTasks[Job].Result);
|
Fun(Tasker[Job].Result);
|
||||||
});
|
});
|
||||||
delete CurrTasks[Job];
|
delete Tasker[Job];
|
||||||
};
|
};
|
||||||
}, 50, Job, Then);
|
}, 50, Job, Then);
|
||||||
return Job;
|
return Job;
|
||||||
|
@ -107,19 +108,20 @@ function MakeWindow(Attrs) {
|
||||||
return Window;
|
return Window;
|
||||||
};
|
};
|
||||||
|
|
||||||
function DisplayChannel(Channel) {
|
function DisplayProfile(Profile) {
|
||||||
var Window = MakeWindow({className: "Channel"});
|
var Window = MakeWindow({className: "Profile"});
|
||||||
Window.innerHTML += `<div class="" style="display: inline-block;">
|
Window.innerHTML += `<div class="" style="display: inline-block;">
|
||||||
<a href="${Channel.Url}">
|
<a href="${Profile.Url}">
|
||||||
<div>
|
<div>
|
||||||
<img class="" src="${Channel.Banner}"/>
|
<img class="" src="${Profile.Banner}"/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<img class="" src="${Channel.Icon}"/>
|
<img class="" src="${Profile.Icon}"/>
|
||||||
${Channel.Name}
|
${Profile.Name}
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
DoAsync(FetchMastodon, FillTimeline);
|
||||||
};
|
};
|
||||||
|
|
||||||
function FetchMastodon(Proc) {
|
function FetchMastodon(Proc) {
|
||||||
|
@ -132,15 +134,15 @@ function FetchMastodon(Proc) {
|
||||||
function ResFetchMastodon(Res) {
|
function ResFetchMastodon(Res) {
|
||||||
var Notes = TransParsers.Mastodon.Status(Res.responseJson);
|
var Notes = TransParsers.Mastodon.Status(Res.responseJson);
|
||||||
LogDebug(Notes, 'l');
|
LogDebug(Notes, 'l');
|
||||||
CurrTasks[Res.Proc[0]].Return(Notes);
|
Tasker[Res.Proc[0]].Return(Notes);
|
||||||
};
|
};
|
||||||
|
|
||||||
function FillTimeline(Notes) {
|
function FillTimeline(Notes) {
|
||||||
Notes.forEach(function(Note){
|
Notes.forEach(function(Note){
|
||||||
TimelineView.innerHTML += `<div class="View Note" data-data="${B64Obj(Note)}">
|
Root.lastChild.innerHTML += `<div class="View Note">
|
||||||
<a href="${Note.Author.Url}" onclick="DisplayChannel(UnB64Obj(this.parentNode.dataset.data).Author); return false;">
|
<a href="${Note.Profile.Url}" onclick="DisplayProfile(ApiCache.Profiles['${Note.Profile.Url}']); return false;">
|
||||||
<img class="Author Icon" src="${Note.Author.Icon}"/>
|
<img class="Profile Icon" src="${Note.Profile.Icon}"/>
|
||||||
${Note.Author.Name}
|
${Note.Profile.Name}
|
||||||
</a>
|
</a>
|
||||||
${Note.Content}
|
${Note.Content}
|
||||||
<a href="${Note.Url}">${Note.Time}</a>
|
<a href="${Note.Url}">${Note.Time}</a>
|
||||||
|
@ -150,7 +152,13 @@ function FillTimeline(Notes) {
|
||||||
|
|
||||||
function FetchFeatured(Proc) {
|
function FetchFeatured(Proc) {
|
||||||
//if (UseFakeApi) {
|
//if (UseFakeApi) {
|
||||||
CurrTasks[Proc[0]].Return(FakeApi.Friendiiverse.Featured);
|
var Featured = FakeApi.Friendiiverse.Featured;
|
||||||
|
Object.values(Featured).forEach(function(Profiles){
|
||||||
|
Profiles.forEach(function(Profile){
|
||||||
|
ApiCache.Profiles[Profile.Url] = Profile;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
Tasker[Proc[0]].Return(Featured);
|
||||||
//} else {
|
//} else {
|
||||||
|
|
||||||
//};
|
//};
|
||||||
|
@ -158,16 +166,16 @@ function FetchFeatured(Proc) {
|
||||||
|
|
||||||
function FillFeatured(Categories) {
|
function FillFeatured(Categories) {
|
||||||
var Window = MakeWindow({className: "Gallery"});
|
var Window = MakeWindow({className: "Gallery"});
|
||||||
Object.values(Categories).forEach(function(Channels){
|
Object.values(Categories).forEach(function(Profiles){
|
||||||
Channels.forEach(function(Channel){
|
Profiles.forEach(function(Profile){
|
||||||
Window.innerHTML += `<div data-data="${B64Obj(Channel)}">
|
Window.innerHTML += `<div>
|
||||||
<a href="${Channel.Url}" onclick="DisplayChannel(UnB64Obj(this.parentNode.dataset.data)); return false;">
|
<a href="${Profile.Url}" onclick="DisplayProfile(ApiCache.Profiles['${Profile.Url}']); return false;">
|
||||||
<div>
|
<div>
|
||||||
<img src="${Channel.Banner}"/>
|
<img src="${Profile.Banner}"/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<img src="${Channel.Icon}"/>
|
<img src="${Profile.Icon}"/>
|
||||||
${Channel.Name}
|
${Profile.Name}
|
||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</div>`;
|
</div>`;
|
||||||
|
|
|
@ -1,3 +1,17 @@
|
||||||
|
:root {
|
||||||
|
--BarHeight: 3em;
|
||||||
|
}
|
||||||
|
|
||||||
|
* {
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
overflow-y: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
img, video {
|
img, video {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
}
|
}
|
||||||
|
@ -9,11 +23,13 @@ img, video {
|
||||||
#Bottom {
|
#Bottom {
|
||||||
display: block;
|
display: block;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
|
height: var(--BarHeight);
|
||||||
|
|
||||||
position: fixed;
|
position: fixed;
|
||||||
bottom: 0;
|
bottom: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
||||||
border: 2px solid black;
|
border: 2px solid black;
|
||||||
margin-top: 4em;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#DataView {
|
#DataView {
|
||||||
|
@ -28,8 +44,9 @@ img, video {
|
||||||
max-width: 100%;
|
max-width: 100%;
|
||||||
min-width: 100%;
|
min-width: 100%;
|
||||||
|
|
||||||
min-height: calc(100% - 4em);
|
height: 100vh;
|
||||||
padding-bottom: 2em;
|
overflow-y: auto;
|
||||||
|
padding-bottom: var(--BarHeight);
|
||||||
}
|
}
|
||||||
|
|
||||||
.View.Note {
|
.View.Note {
|
||||||
|
@ -37,7 +54,7 @@ img, video {
|
||||||
margin: 12px;
|
margin: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.View.Note .Author.Icon {
|
.View.Note .Profile.Icon {
|
||||||
width: 64px;
|
width: 64px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue