Api and UI updates

This commit is contained in:
octospacc 2023-04-22 17:09:59 +02:00
parent dee3883537
commit 0ec5864e54
4 changed files with 82 additions and 56 deletions

View File

@ -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) {

View File

@ -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>

View File

@ -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>`;

View File

@ -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 {
@ -23,13 +39,14 @@ img, video {
.Window { .Window {
background: white; background: white;
position: absolute; position: absolute;
width: 100%; width: 100%;
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;
} }