2023-04-23 19:46:01 +02:00
|
|
|
var Persist = {Servers: {}, Sources: {}, Identities: {},};
|
|
|
|
var Present = CopyObj(Persist);
|
2023-04-22 17:09:59 +02:00
|
|
|
var Tasker = {};
|
2023-04-25 00:55:20 +02:00
|
|
|
var ApiCache = {
|
|
|
|
__Store__(Data, Key, Where) {
|
|
|
|
ApiCache[Where][Key] = Data;
|
|
|
|
ApiCache[Where][Key].__Time__ = Date.now();
|
|
|
|
},
|
|
|
|
__UrlStore__(Data) {
|
|
|
|
ApiCache.__Store__(Data, Data.Url, 'Urls');
|
|
|
|
},
|
|
|
|
Urls: {},
|
|
|
|
};
|
2023-04-19 00:16:35 +02:00
|
|
|
|
2023-04-24 15:03:51 +02:00
|
|
|
Assets._ = function _(Name) {
|
|
|
|
if (Name in Assets) {
|
|
|
|
if (Assets[Name].startsWith('data:')) {
|
|
|
|
return Assets[Name];
|
|
|
|
} else {
|
|
|
|
return `./Assets/${Assets[Name]}`;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-04-25 00:55:20 +02:00
|
|
|
Strings._ = function _(Name) {
|
|
|
|
// TODO: Handle arbitrary nestation
|
|
|
|
if (Name in Strings) {
|
|
|
|
if (Strings[Name]['en']) { // TODO{ Select this language from user config
|
|
|
|
return Strings[Name]['en'];
|
|
|
|
} else {
|
|
|
|
return Strings[Name].en;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
2023-04-19 18:06:08 +02:00
|
|
|
function DoAsync(First, Then, Data) {
|
|
|
|
var Job = RndId();
|
2023-04-22 17:09:59 +02:00
|
|
|
Tasker[Job] = {
|
2023-04-19 18:06:08 +02:00
|
|
|
Remains: 0,
|
|
|
|
Return(Data) {
|
|
|
|
this.Remains -= 1;
|
|
|
|
this.Result = Data;
|
|
|
|
},
|
2023-04-19 00:16:35 +02:00
|
|
|
};
|
2023-04-19 18:06:08 +02:00
|
|
|
// Call all First functs
|
2023-04-25 15:00:41 +02:00
|
|
|
ForceList(First).forEach(function(Fun){
|
2023-04-19 12:18:14 +02:00
|
|
|
var Task = RndId();
|
2023-04-19 18:06:08 +02:00
|
|
|
var Proc = [Job, Task];
|
2023-04-22 17:09:59 +02:00
|
|
|
Tasker[Job][Task] = {};
|
|
|
|
Tasker[Job].Remains += 1;
|
2023-04-19 18:06:08 +02:00
|
|
|
//Fun(Proc, Data);
|
|
|
|
Data ? Fun(Data, Proc) : Fun(Proc);
|
2023-04-19 12:18:14 +02:00
|
|
|
});
|
2023-04-19 18:06:08 +02:00
|
|
|
// Continuosly check when First functs completed
|
2023-04-22 17:09:59 +02:00
|
|
|
Tasker[Job].Interval = setInterval(function(Job, Then){
|
|
|
|
if (Tasker[Job].Remains <= 0) {
|
|
|
|
clearInterval(Tasker[Job].Interval);
|
2023-04-19 18:06:08 +02:00
|
|
|
// Call all Then functs
|
2023-04-19 12:18:14 +02:00
|
|
|
ForceList(Then).forEach(function(Fun){
|
2023-04-22 17:09:59 +02:00
|
|
|
Fun(Tasker[Job].Result);
|
2023-04-19 12:18:14 +02:00
|
|
|
});
|
2023-04-22 17:09:59 +02:00
|
|
|
delete Tasker[Job];
|
2023-04-19 12:18:14 +02:00
|
|
|
};
|
2023-04-19 18:06:08 +02:00
|
|
|
}, 50, Job, Then);
|
|
|
|
return Job;
|
2023-04-19 12:18:14 +02:00
|
|
|
};
|
|
|
|
|
2023-04-25 23:35:34 +02:00
|
|
|
function HtmlAssign(Id, Data) {
|
2023-04-26 15:33:51 +02:00
|
|
|
Array.from(document.getElementsByClassName(Id)).forEach(function(El){
|
|
|
|
HtmlAssignPropper(El, Data);
|
|
|
|
});
|
|
|
|
Array.from(document.getElementById(Id).querySelectorAll(`*:not([class~="${Id}"])`)).forEach(function(El){
|
|
|
|
if (El.dataset.assign) {
|
|
|
|
HtmlAssignPropper(El, Data);
|
|
|
|
};
|
|
|
|
});
|
|
|
|
};
|
|
|
|
function HtmlAssignPropper(El, Data) {
|
|
|
|
El.dataset.assign.trim().split(' ').forEach(function(Att){
|
|
|
|
var Toks = Att.split(':');
|
|
|
|
var Prop = Data;
|
|
|
|
Toks[1].split('.').forEach(function(Key){
|
|
|
|
Prop = Prop[Key];
|
|
|
|
});
|
|
|
|
if (Prop !== undefined) {
|
|
|
|
El[Toks[0]] = Prop;
|
2023-04-25 23:35:34 +02:00
|
|
|
};
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2023-04-22 17:09:59 +02:00
|
|
|
function DisplayProfile(Profile) {
|
2023-04-26 15:33:51 +02:00
|
|
|
Profile = UrlObj(Profile);
|
2023-04-25 00:55:20 +02:00
|
|
|
var Window = MkWindow({className: "Profile"});
|
2023-04-22 10:06:31 +02:00
|
|
|
Window.innerHTML += `<div class="" style="display: inline-block;">
|
2023-04-22 17:09:59 +02:00
|
|
|
<a href="${Profile.Url}">
|
2023-04-22 10:06:31 +02:00
|
|
|
<div>
|
2023-04-22 17:09:59 +02:00
|
|
|
<img class="" src="${Profile.Banner}"/>
|
2023-04-22 10:06:31 +02:00
|
|
|
</div>
|
|
|
|
<div>
|
2023-04-22 17:09:59 +02:00
|
|
|
<img class="" src="${Profile.Icon}"/>
|
|
|
|
${Profile.Name}
|
2023-04-22 10:06:31 +02:00
|
|
|
</div>
|
|
|
|
</a>
|
|
|
|
</div>`;
|
2023-04-26 15:33:51 +02:00
|
|
|
// TODO: Handle fetching notes of non-standard profiles like servers timelines
|
2023-04-25 15:00:41 +02:00
|
|
|
DoAsync(FetchNotes, FillTimeline, Profile);
|
|
|
|
};
|
|
|
|
|
|
|
|
function DisplayMastodonTimeline(Data) {
|
|
|
|
var Window = MkWindow();
|
|
|
|
Window.innerHTML += `<div class="" style="display: inline-block;">
|
|
|
|
<a href="${Profile.Url}">
|
|
|
|
<div>
|
|
|
|
<img class="" src="${Profile.Banner}"/>
|
|
|
|
</div>
|
|
|
|
<div>
|
|
|
|
<img class="" src="${Profile.Icon}"/>
|
|
|
|
${Profile.Name}
|
|
|
|
</div>
|
|
|
|
</a>
|
|
|
|
</div>`;
|
|
|
|
DoAsync(FetchNotes, FillTimeline, Profile);
|
2023-04-23 19:46:01 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
function FetchNotes(Profile, Proc) {
|
2023-04-25 00:55:20 +02:00
|
|
|
var Soft = Profile.__Software__;
|
2023-04-25 15:00:41 +02:00
|
|
|
NetApiCall({Target: UrlBase(Profile.Url), Method: ApiEndpoints.FetchNotes['Mastodon'](Profile), CallFine: function(Res){
|
|
|
|
var Notes = ApiTransform(Res.responseJson, Soft, 'Note');
|
2023-04-25 00:55:20 +02:00
|
|
|
LogDebug(Notes, 'l');
|
|
|
|
Tasker[Res.Proc[0]].Return(Notes);
|
|
|
|
}}, Proc);
|
2023-04-20 22:08:38 +02:00
|
|
|
};
|
2023-04-19 00:16:35 +02:00
|
|
|
|
2023-04-19 12:18:14 +02:00
|
|
|
function FetchMastodon(Proc) {
|
2023-04-25 15:00:41 +02:00
|
|
|
//if (UseFakeApi) {
|
|
|
|
// ResFetchMastodon({responseJson: [FakeApi.Mastodon.Status], Proc: Proc});
|
|
|
|
//} else {
|
|
|
|
NetApiCall({Target: "Mastodon", Method: "GET timelines/public", CallFine: ResFetchMastodon}, Proc);
|
|
|
|
//};
|
2023-04-19 00:16:35 +02:00
|
|
|
};
|
2023-04-20 18:13:47 +02:00
|
|
|
function ResFetchMastodon(Res) {
|
2023-04-23 00:48:14 +02:00
|
|
|
var Notes = ApiTransform(Res.responseJson, 'Mastodon', 'Note');
|
2023-04-20 18:13:47 +02:00
|
|
|
LogDebug(Notes, 'l');
|
2023-04-22 17:09:59 +02:00
|
|
|
Tasker[Res.Proc[0]].Return(Notes);
|
2023-04-20 18:13:47 +02:00
|
|
|
};
|
2023-04-19 00:16:35 +02:00
|
|
|
|
|
|
|
function FillTimeline(Notes) {
|
|
|
|
Notes.forEach(function(Note){
|
2023-04-25 00:55:20 +02:00
|
|
|
ApiCache.__UrlStore__(Note.Profile);
|
2023-04-22 17:09:59 +02:00
|
|
|
Root.lastChild.innerHTML += `<div class="View Note">
|
2023-04-23 19:46:01 +02:00
|
|
|
<a href="${Note.Profile.Url}" onclick="DisplayProfile(ApiCache.Urls['${Note.Profile.Url}']); return false;">
|
2023-04-22 17:09:59 +02:00
|
|
|
<img class="Profile Icon" src="${Note.Profile.Icon}"/>
|
|
|
|
${Note.Profile.Name}
|
2023-04-20 00:19:19 +02:00
|
|
|
</a>
|
2023-04-25 00:55:20 +02:00
|
|
|
${SanitizeHtml(Note.Content)}
|
2023-04-20 15:17:00 +02:00
|
|
|
<a href="${Note.Url}">${Note.Time}</a>
|
2023-04-19 00:16:35 +02:00
|
|
|
</div>`;
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2023-04-25 23:35:34 +02:00
|
|
|
function FillHome() {
|
2023-04-25 00:55:20 +02:00
|
|
|
var Window = MkWindow({className: "Gallery"});
|
2023-04-25 23:35:34 +02:00
|
|
|
var Categories = ApiStatic.Featured;
|
|
|
|
Object.keys(Categories).forEach(function(Category){
|
|
|
|
Window.innerHTML += `<h2>Featured ${Category}</h2>`;
|
|
|
|
Categories[Category].forEach(function(Profile){
|
|
|
|
ApiCache.Urls[Profile.Url] = Profile;
|
|
|
|
var Rnd = RndHtmlId();
|
2023-04-26 15:33:51 +02:00
|
|
|
Window.innerHTML += `<div id="${Rnd}">
|
|
|
|
<a href="${Profile.Url}" onclick="DisplayProfile('${Profile.Url}'); return false;">
|
2023-04-20 22:08:38 +02:00
|
|
|
<div>
|
2023-04-26 15:33:51 +02:00
|
|
|
<img data-assign="src:Banner" src="${Profile.Banner}"/>
|
2023-04-20 22:08:38 +02:00
|
|
|
</div>
|
|
|
|
<div>
|
2023-04-26 15:33:51 +02:00
|
|
|
<img data-assign="src:Icon" src="${Profile.Icon}"/>
|
|
|
|
<span data-assign="innerHTML:Name">${Profile.Url}</span>
|
2023-04-20 22:08:38 +02:00
|
|
|
</div>
|
2023-04-20 18:13:47 +02:00
|
|
|
</a>
|
|
|
|
</div>`;
|
2023-04-26 15:33:51 +02:00
|
|
|
NetApiCall({Target: Profile.Url, Method: ApiEndpoints.ServerInfo[Profile.ServerSoftware], CallFine: function(Res){
|
|
|
|
var Data = ApiTransform(Res.responseJson, Profile.ServerSoftware, 'Profile');
|
|
|
|
HtmlAssign(Rnd, Data);
|
|
|
|
_.merge(ApiCache.Urls[Profile.Url], Data);
|
2023-04-25 23:35:34 +02:00
|
|
|
}});
|
2023-04-20 18:13:47 +02:00
|
|
|
});
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
2023-04-20 22:08:38 +02:00
|
|
|
/*
|
2023-04-19 00:16:35 +02:00
|
|
|
PlazasView.innerHTML = `
|
|
|
|
<div>
|
|
|
|
<h3>Featured</h3>
|
|
|
|
<ul>
|
|
|
|
<li onclick="DisplayFriendicaTimeline('statuses/networkpublic_timeline');">Federation</li>
|
|
|
|
<li onclick="DisplayFriendicaTimeline('statuses/public_timeline');">${FriendicaUrl}</li>
|
2023-04-19 18:06:08 +02:00
|
|
|
<li onclick="DoAsync(FetchMastodon, FillTimeline);">
|
|
|
|
<img src=""/>
|
|
|
|
${MastodonUrl}
|
|
|
|
</li>
|
2023-04-19 00:16:35 +02:00
|
|
|
</ul>
|
|
|
|
</div>
|
|
|
|
`;
|
2023-04-20 22:08:38 +02:00
|
|
|
*/
|
2023-04-20 18:13:47 +02:00
|
|
|
|
2023-04-23 00:48:14 +02:00
|
|
|
function ComposeNote() {
|
2023-04-25 00:55:20 +02:00
|
|
|
var Window = MkWindow();
|
2023-04-23 00:48:14 +02:00
|
|
|
Window.innerHTML += `
|
|
|
|
<h2>Compose</h2>
|
2023-04-23 19:46:01 +02:00
|
|
|
<p>Posting in: [Channel]</p>
|
2023-04-23 00:48:14 +02:00
|
|
|
<textarea style="width: 100%; height: 20em;"></textarea>
|
|
|
|
<p>
|
|
|
|
<button onclick="PostNote(this.parentNode.parentNode.querySelector('textarea').value);">Note!</button>
|
|
|
|
</p>
|
|
|
|
`;
|
|
|
|
};
|
|
|
|
function PostNote(Text) {
|
|
|
|
Obj = ExtrimObj(ApiSchema.Note);
|
2023-04-23 19:46:01 +02:00
|
|
|
Obj.Content = Text;
|
|
|
|
// Find out current profile and destination channel to do a proper net request
|
|
|
|
};
|
|
|
|
|
|
|
|
function ManageSettings() {
|
2023-04-25 00:55:20 +02:00
|
|
|
MkWindow().innerHTML = `
|
2023-04-24 15:03:51 +02:00
|
|
|
<h2>Settings</h2>
|
|
|
|
<h3>Misc</h3>
|
|
|
|
<p>
|
2023-04-25 00:55:20 +02:00
|
|
|
Language: ${MkSelectMenu([{innerHTML: "en"}, {innerHTML: "it"},]).outerHTML}
|
2023-04-24 15:03:51 +02:00
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
Theme:
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
<label>Wait <input type="number"/> seconds after clicking send for a note to be sent</label>
|
|
|
|
</p>
|
|
|
|
<h3>Identities</h3>
|
2023-04-25 23:35:34 +02:00
|
|
|
${MkListMenu(Present.Identities, ElsCfg.ListMenu.FullControl).outerHTML}
|
2023-04-24 15:03:51 +02:00
|
|
|
<h3>Sources</h3>
|
2023-04-25 23:35:34 +02:00
|
|
|
${MkListMenu(Present.Sources, ElsCfg.ListMenu.FullControl).outerHTML}
|
2023-04-24 15:03:51 +02:00
|
|
|
<h3>Data</h3>
|
|
|
|
<p>
|
|
|
|
<button>Import User Data</button>
|
|
|
|
<button>Export User Data</button>
|
|
|
|
</p>
|
|
|
|
<p>
|
|
|
|
<label><input type="checkbox"/> Persist cache on app reload</label>
|
|
|
|
</p>
|
2023-04-23 19:46:01 +02:00
|
|
|
`;
|
2023-04-23 00:48:14 +02:00
|
|
|
};
|
|
|
|
|
2023-04-25 23:35:34 +02:00
|
|
|
FillHome();
|
2023-04-22 10:06:31 +02:00
|
|
|
CoverView.remove();
|