mirror of
https://github.com/C9Glax/tranga.git
synced 2025-07-04 01:44:17 +02:00
Compare commits
10 Commits
c9537a9963
...
1.1.1
Author | SHA1 | Date | |
---|---|---|---|
732c2f119c | |||
81638f4b4a | |||
c547aa6422 | |||
d80980512e | |||
f9f802155d | |||
eef0955009 | |||
ec25900ac0 | |||
e5fe14a09e | |||
5dc91095f8 | |||
985ac8fc7a |
@ -60,7 +60,8 @@ public abstract class Connector
|
|||||||
/// Retrieves the Cover from the Website
|
/// Retrieves the Cover from the Website
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="publication">Publication to retrieve Cover for</param>
|
/// <param name="publication">Publication to retrieve Cover for</param>
|
||||||
public abstract void DownloadCover(Publication publication);
|
/// <param name="settings">TrangaSettings</param>
|
||||||
|
public abstract void CloneCoverFromCache(Publication publication, TrangaSettings settings);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the series-info to series.json in the Publication Folder
|
/// Saves the series-info to series.json in the Publication Folder
|
||||||
@ -86,7 +87,7 @@ public abstract class Connector
|
|||||||
/// <returns>XML-string</returns>
|
/// <returns>XML-string</returns>
|
||||||
protected static string CreateComicInfo(Publication publication, Chapter chapter, Logger? logger)
|
protected static string CreateComicInfo(Publication publication, Chapter chapter, Logger? logger)
|
||||||
{
|
{
|
||||||
logger?.WriteLine("Connector", $"Creating ComicInfo.Xml for {publication.sortName} Chapter {chapter.volumeNumber} {chapter.chapterNumber}");
|
logger?.WriteLine("Connector", $"Creating ComicInfo.Xml for {publication.sortName} {publication.internalId} {chapter.volumeNumber}-{chapter.chapterNumber}");
|
||||||
XElement comicInfo = new XElement("ComicInfo",
|
XElement comicInfo = new XElement("ComicInfo",
|
||||||
new XElement("Tags", string.Join(',',publication.tags)),
|
new XElement("Tags", string.Join(',',publication.tags)),
|
||||||
new XElement("LanguageISO", publication.originalLanguage),
|
new XElement("LanguageISO", publication.originalLanguage),
|
||||||
@ -137,11 +138,12 @@ public abstract class Connector
|
|||||||
/// <param name="imageUrls">List of URLs to download Images from</param>
|
/// <param name="imageUrls">List of URLs to download Images from</param>
|
||||||
/// <param name="saveArchiveFilePath">Full path to save archive to (without file ending .cbz)</param>
|
/// <param name="saveArchiveFilePath">Full path to save archive to (without file ending .cbz)</param>
|
||||||
/// <param name="downloadClient">DownloadClient of the connector</param>
|
/// <param name="downloadClient">DownloadClient of the connector</param>
|
||||||
|
/// <param name="logger"></param>
|
||||||
/// <param name="comicInfoPath">Path of the generate Chapter ComicInfo.xml, if it was generated</param>
|
/// <param name="comicInfoPath">Path of the generate Chapter ComicInfo.xml, if it was generated</param>
|
||||||
/// <param name="requestType">RequestType for RateLimits</param>
|
/// <param name="requestType">RequestType for RateLimits</param>
|
||||||
protected static void DownloadChapterImages(string[] imageUrls, string saveArchiveFilePath, DownloadClient downloadClient, byte requestType, Logger? logger, string? comicInfoPath = null)
|
protected static void DownloadChapterImages(string[] imageUrls, string saveArchiveFilePath, DownloadClient downloadClient, byte requestType, Logger? logger, string? comicInfoPath = null)
|
||||||
{
|
{
|
||||||
logger?.WriteLine("Connector", "Downloading Images");
|
logger?.WriteLine("Connector", $"Downloading Images for {saveArchiveFilePath}");
|
||||||
//Check if Publication Directory already exists
|
//Check if Publication Directory already exists
|
||||||
string directoryPath = Path.GetDirectoryName(saveArchiveFilePath)!;
|
string directoryPath = Path.GetDirectoryName(saveArchiveFilePath)!;
|
||||||
if (!Directory.Exists(directoryPath))
|
if (!Directory.Exists(directoryPath))
|
||||||
@ -159,13 +161,14 @@ public abstract class Connector
|
|||||||
{
|
{
|
||||||
string[] split = imageUrl.Split('.');
|
string[] split = imageUrl.Split('.');
|
||||||
string extension = split[^1];
|
string extension = split[^1];
|
||||||
|
logger?.WriteLine("Connector", $"Downloading Image {chapter + 1}/{imageUrls.Length}");
|
||||||
DownloadImage(imageUrl, Path.Join(tempFolder, $"{chapter++}.{extension}"), downloadClient, requestType);
|
DownloadImage(imageUrl, Path.Join(tempFolder, $"{chapter++}.{extension}"), downloadClient, requestType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(comicInfoPath is not null)
|
if(comicInfoPath is not null)
|
||||||
File.Copy(comicInfoPath, Path.Join(tempFolder, "ComicInfo.xml"));
|
File.Copy(comicInfoPath, Path.Join(tempFolder, "ComicInfo.xml"));
|
||||||
|
|
||||||
logger?.WriteLine("Connector", "Creating archive");
|
logger?.WriteLine("Connector", $"Creating archive {saveArchiveFilePath}");
|
||||||
//ZIP-it and ship-it
|
//ZIP-it and ship-it
|
||||||
ZipFile.CreateFromDirectory(tempFolder, saveArchiveFilePath);
|
ZipFile.CreateFromDirectory(tempFolder, saveArchiveFilePath);
|
||||||
Directory.Delete(tempFolder, true); //Cleanup
|
Directory.Delete(tempFolder, true); //Cleanup
|
||||||
@ -227,6 +230,7 @@ public abstract class Connector
|
|||||||
catch (HttpRequestException e)
|
catch (HttpRequestException e)
|
||||||
{
|
{
|
||||||
logger?.WriteLine(this.GetType().ToString(), e.Message);
|
logger?.WriteLine(this.GetType().ToString(), e.Message);
|
||||||
|
logger?.WriteLine(this.GetType().ToString(), $"Waiting {_rateLimit[requestType] * 2}");
|
||||||
Thread.Sleep(_rateLimit[requestType] * 2);
|
Thread.Sleep(_rateLimit[requestType] * 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ public class MangaDex : Connector
|
|||||||
total = result["total"]!.GetValue<int>(); //Update the total number of Publications
|
total = result["total"]!.GetValue<int>(); //Update the total number of Publications
|
||||||
|
|
||||||
JsonArray mangaInResult = result["data"]!.AsArray(); //Manga-data-Array
|
JsonArray mangaInResult = result["data"]!.AsArray(); //Manga-data-Array
|
||||||
|
logger?.WriteLine(this.GetType().ToString(), $"Getting publication data.");
|
||||||
//Loop each Manga and extract information from JSON
|
//Loop each Manga and extract information from JSON
|
||||||
foreach (JsonNode? mangeNode in mangaInResult)
|
foreach (JsonNode? mangeNode in mangaInResult)
|
||||||
{
|
{
|
||||||
@ -142,12 +143,13 @@ public class MangaDex : Connector
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
logger?.WriteLine(this.GetType().ToString(), $"Done getting publications (title={publicationTitle})");
|
||||||
return publications.ToArray();
|
return publications.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override Chapter[] GetChapters(Publication publication, string language = "")
|
public override Chapter[] GetChapters(Publication publication, string language = "")
|
||||||
{
|
{
|
||||||
logger?.WriteLine(this.GetType().ToString(), $"Getting Chapters {publication.sortName} (language={language})");
|
logger?.WriteLine(this.GetType().ToString(), $"Getting Chapters for {publication.sortName} {publication.internalId} (language={language})");
|
||||||
const int limit = 100; //How many values we want returned at once
|
const int limit = 100; //How many values we want returned at once
|
||||||
int offset = 0; //"Page"
|
int offset = 0; //"Page"
|
||||||
int total = int.MaxValue; //How many total results are there, is updated on first request
|
int total = int.MaxValue; //How many total results are there, is updated on first request
|
||||||
@ -197,12 +199,13 @@ public class MangaDex : Connector
|
|||||||
{
|
{
|
||||||
NumberDecimalSeparator = "."
|
NumberDecimalSeparator = "."
|
||||||
};
|
};
|
||||||
|
logger?.WriteLine(this.GetType().ToString(), $"Done getting Chapters for {publication.internalId}");
|
||||||
return chapters.OrderBy(chapter => Convert.ToSingle(chapter.chapterNumber, chapterNumberFormatInfo)).ToArray();
|
return chapters.OrderBy(chapter => Convert.ToSingle(chapter.chapterNumber, chapterNumberFormatInfo)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DownloadChapter(Publication publication, Chapter chapter)
|
public override void DownloadChapter(Publication publication, Chapter chapter)
|
||||||
{
|
{
|
||||||
logger?.WriteLine(this.GetType().ToString(), $"Download Chapter {publication.sortName} {chapter.volumeNumber}-{chapter.chapterNumber}");
|
logger?.WriteLine(this.GetType().ToString(), $"Downloading Chapter-Info {publication.sortName} {publication.internalId} {chapter.volumeNumber}-{chapter.chapterNumber}");
|
||||||
//Request URLs for Chapter-Images
|
//Request URLs for Chapter-Images
|
||||||
DownloadClient.RequestResult requestResult =
|
DownloadClient.RequestResult requestResult =
|
||||||
downloadClient.MakeRequest($"https://api.mangadex.org/at-home/server/{chapter.url}?forcePort443=false'", (byte)RequestType.AtHomeServer);
|
downloadClient.MakeRequest($"https://api.mangadex.org/at-home/server/{chapter.url}?forcePort443=false'", (byte)RequestType.AtHomeServer);
|
||||||
@ -229,9 +232,10 @@ public class MangaDex : Connector
|
|||||||
|
|
||||||
private string? GetCoverUrl(string publicationId, string? posterId)
|
private string? GetCoverUrl(string publicationId, string? posterId)
|
||||||
{
|
{
|
||||||
|
logger?.WriteLine(this.GetType().ToString(), $"Getting CoverUrl for {publicationId}");
|
||||||
if (posterId is null)
|
if (posterId is null)
|
||||||
{
|
{
|
||||||
logger?.WriteLine(this.GetType().ToString(), $"No posterId");
|
logger?.WriteLine(this.GetType().ToString(), $"No posterId, aborting");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -247,6 +251,7 @@ public class MangaDex : Connector
|
|||||||
string fileName = result["data"]!["attributes"]!["fileName"]!.GetValue<string>();
|
string fileName = result["data"]!["attributes"]!["fileName"]!.GetValue<string>();
|
||||||
|
|
||||||
string coverUrl = $"https://uploads.mangadex.org/covers/{publicationId}/{fileName}";
|
string coverUrl = $"https://uploads.mangadex.org/covers/{publicationId}/{fileName}";
|
||||||
|
logger?.WriteLine(this.GetType().ToString(), $"Got Cover-Url for {publicationId} -> {coverUrl}");
|
||||||
return coverUrl;
|
return coverUrl;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,14 +269,16 @@ public class MangaDex : Connector
|
|||||||
return null;
|
return null;
|
||||||
|
|
||||||
string author = result["data"]!["attributes"]!["name"]!.GetValue<string>();
|
string author = result["data"]!["attributes"]!["name"]!.GetValue<string>();
|
||||||
|
logger?.WriteLine(this.GetType().ToString(), $"Got author {authorId} -> {author}");
|
||||||
return author;
|
return author;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void DownloadCover(Publication publication)
|
public override void CloneCoverFromCache(Publication publication, TrangaSettings settings)
|
||||||
{
|
{
|
||||||
logger?.WriteLine(this.GetType().ToString(), $"Download cover {publication.sortName}");
|
logger?.WriteLine(this.GetType().ToString(), $"Cloning cover {publication.sortName}");
|
||||||
//Check if Publication already has a Folder and cover
|
//Check if Publication already has a Folder and cover
|
||||||
string publicationFolder = Path.Join(downloadLocation, publication.folderName);
|
string publicationFolder = Path.Join(downloadLocation, publication.folderName);
|
||||||
|
|
||||||
if(!Directory.Exists(publicationFolder))
|
if(!Directory.Exists(publicationFolder))
|
||||||
Directory.CreateDirectory(publicationFolder);
|
Directory.CreateDirectory(publicationFolder);
|
||||||
DirectoryInfo dirInfo = new (publicationFolder);
|
DirectoryInfo dirInfo = new (publicationFolder);
|
||||||
@ -281,21 +288,10 @@ public class MangaDex : Connector
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (publication.posterUrl is null || publication.posterUrl!.Contains("http"))
|
string fileInCache = Path.Join(settings.coverImageCache, publication.coverFileNameInCache);
|
||||||
{
|
string newFilePath = Path.Join(publicationFolder, $"cover.{Path.GetFileName(fileInCache).Split('.')[^1]}" );
|
||||||
logger?.WriteLine(this.GetType().ToString(), $"No Poster-URL in publication");
|
logger?.WriteLine(this.GetType().ToString(), $"Cloning cover {fileInCache} -> {newFilePath}");
|
||||||
return;
|
File.Copy(fileInCache, newFilePath, true);
|
||||||
}
|
|
||||||
|
|
||||||
//Get file-extension (jpg, png)
|
|
||||||
string[] split = publication.posterUrl.Split('.');
|
|
||||||
string extension = split[^1];
|
|
||||||
|
|
||||||
string outFolderPath = Path.Join(downloadLocation, publication.folderName);
|
|
||||||
Directory.CreateDirectory(outFolderPath);
|
|
||||||
|
|
||||||
//Download cover-Image
|
|
||||||
DownloadImage(publication.posterUrl, Path.Join(downloadLocation, publication.folderName, $"cover.{extension}"), this.downloadClient, (byte)RequestType.AtHomeServer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private string SaveImage(string url)
|
private string SaveImage(string url)
|
||||||
@ -311,6 +307,7 @@ public class MangaDex : Connector
|
|||||||
using MemoryStream ms = new();
|
using MemoryStream ms = new();
|
||||||
coverResult.result.CopyTo(ms);
|
coverResult.result.CopyTo(ms);
|
||||||
File.WriteAllBytes(saveImagePath, ms.ToArray());
|
File.WriteAllBytes(saveImagePath, ms.ToArray());
|
||||||
|
logger?.WriteLine(this.GetType().ToString(), $"Saving image to {saveImagePath}");
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -37,7 +37,7 @@ public static class TaskExecutor
|
|||||||
switch (trangaTask.task)
|
switch (trangaTask.task)
|
||||||
{
|
{
|
||||||
case TrangaTask.Task.DownloadNewChapters:
|
case TrangaTask.Task.DownloadNewChapters:
|
||||||
DownloadNewChapters(connector!, (Publication)trangaTask.publication!, trangaTask.language, ref taskManager._chapterCollection);
|
DownloadNewChapters(connector!, (Publication)trangaTask.publication!, trangaTask.language, ref taskManager._chapterCollection, taskManager.settings);
|
||||||
break;
|
break;
|
||||||
case TrangaTask.Task.UpdateChapters:
|
case TrangaTask.Task.UpdateChapters:
|
||||||
UpdateChapters(connector!, (Publication)trangaTask.publication!, trangaTask.language, ref taskManager._chapterCollection);
|
UpdateChapters(connector!, (Publication)trangaTask.publication!, trangaTask.language, ref taskManager._chapterCollection);
|
||||||
@ -90,7 +90,7 @@ public static class TaskExecutor
|
|||||||
/// <param name="publication">Publication to check</param>
|
/// <param name="publication">Publication to check</param>
|
||||||
/// <param name="language">Language to receive chapters for</param>
|
/// <param name="language">Language to receive chapters for</param>
|
||||||
/// <param name="chapterCollection"></param>
|
/// <param name="chapterCollection"></param>
|
||||||
private static void DownloadNewChapters(Connector connector, Publication publication, string language, ref Dictionary<Publication, List<Chapter>> chapterCollection)
|
private static void DownloadNewChapters(Connector connector, Publication publication, string language, ref Dictionary<Publication, List<Chapter>> chapterCollection, TrangaSettings settings)
|
||||||
{
|
{
|
||||||
//Check if Publication already has a Folder
|
//Check if Publication already has a Folder
|
||||||
string publicationFolder = Path.Join(connector.downloadLocation, publication.folderName);
|
string publicationFolder = Path.Join(connector.downloadLocation, publication.folderName);
|
||||||
@ -98,7 +98,7 @@ public static class TaskExecutor
|
|||||||
Directory.CreateDirectory(publicationFolder);
|
Directory.CreateDirectory(publicationFolder);
|
||||||
List<Chapter> newChapters = UpdateChapters(connector, publication, language, ref chapterCollection);
|
List<Chapter> newChapters = UpdateChapters(connector, publication, language, ref chapterCollection);
|
||||||
|
|
||||||
connector.DownloadCover(publication);
|
connector.CloneCoverFromCache(publication, settings);
|
||||||
|
|
||||||
string seriesInfoPath = Path.Join(publicationFolder, "series.json");
|
string seriesInfoPath = Path.Join(publicationFolder, "series.json");
|
||||||
if(!File.Exists(seriesInfoPath))
|
if(!File.Exists(seriesInfoPath))
|
||||||
|
BIN
Website/favicon.ico
Normal file
BIN
Website/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
@ -66,8 +66,11 @@
|
|||||||
The total opposite of his ideal male body!
|
The total opposite of his ideal male body!
|
||||||
Pandemic love comedy!
|
Pandemic love comedy!
|
||||||
</publication-description>
|
</publication-description>
|
||||||
<publication-delete>Delete Task ❌</publication-delete>
|
<publication-interactions>
|
||||||
<publication-add>Add Task ➕</publication-add>
|
<publication-starttask>Start Task ▶️</publication-starttask>
|
||||||
|
<publication-delete>Delete Task ❌</publication-delete>
|
||||||
|
<publication-add>Add Task ➕</publication-add>
|
||||||
|
</publication-interactions>
|
||||||
</publication-information>
|
</publication-information>
|
||||||
</publication-viewer>
|
</publication-viewer>
|
||||||
</popup>
|
</popup>
|
||||||
|
@ -18,6 +18,7 @@ const publicationViewerAuthor = document.querySelector("#publicationViewerAuthor
|
|||||||
const pubviewcover = document.querySelector("#pubviewcover");
|
const pubviewcover = document.querySelector("#pubviewcover");
|
||||||
const publicationDelete = document.querySelector("publication-delete");
|
const publicationDelete = document.querySelector("publication-delete");
|
||||||
const publicationAdd = document.querySelector("publication-add");
|
const publicationAdd = document.querySelector("publication-add");
|
||||||
|
const publicationTaskStart = document.querySelector("publication-starttask");
|
||||||
const closetaskpopup = document.querySelector("#closePopupImg");
|
const closetaskpopup = document.querySelector("#closePopupImg");
|
||||||
const settingDownloadLocation = document.querySelector("#downloadLocation");
|
const settingDownloadLocation = document.querySelector("#downloadLocation");
|
||||||
const settingKomgaUrl = document.querySelector("#komgaUrl");
|
const settingKomgaUrl = document.querySelector("#komgaUrl");
|
||||||
@ -39,6 +40,7 @@ document.querySelector("#blurBackgroundTaskPopup").addEventListener("click", ()
|
|||||||
document.querySelector("#blurBackgroundPublicationPopup").addEventListener("click", () => HidePublicationPopup());
|
document.querySelector("#blurBackgroundPublicationPopup").addEventListener("click", () => HidePublicationPopup());
|
||||||
publicationDelete.addEventListener("click", () => DeleteTaskClick());
|
publicationDelete.addEventListener("click", () => DeleteTaskClick());
|
||||||
publicationAdd.addEventListener("click", () => AddTaskClick());
|
publicationAdd.addEventListener("click", () => AddTaskClick());
|
||||||
|
publicationTaskStart.addEventListener("click", () => StartTaskClick());
|
||||||
settingApiUri.addEventListener("keypress", (event) => {
|
settingApiUri.addEventListener("keypress", (event) => {
|
||||||
if(event.key === "Enter"){
|
if(event.key === "Enter"){
|
||||||
apiUri = settingApiUri.value;
|
apiUri = settingApiUri.value;
|
||||||
@ -130,6 +132,12 @@ function AddTaskClick(){
|
|||||||
HidePublicationPopup();
|
HidePublicationPopup();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function StartTaskClick(){
|
||||||
|
var toEditTask = tasks.filter(task => task.publication.internalId == toEditId)[0];
|
||||||
|
StartTask("DownloadNewChapters", toEditTask.connectorName, toEditId);
|
||||||
|
HidePublicationPopup();
|
||||||
|
}
|
||||||
|
|
||||||
function ResetContent(){
|
function ResetContent(){
|
||||||
//Delete everything
|
//Delete everything
|
||||||
tasksContent.replaceChildren();
|
tasksContent.replaceChildren();
|
||||||
@ -144,8 +152,6 @@ function ResetContent(){
|
|||||||
tasksContent.appendChild(add);
|
tasksContent.appendChild(add);
|
||||||
}
|
}
|
||||||
function ShowPublicationViewerWindow(publicationId, event, add){
|
function ShowPublicationViewerWindow(publicationId, event, add){
|
||||||
|
|
||||||
|
|
||||||
//Show popup
|
//Show popup
|
||||||
publicationViewerPopup.style.display = "block";
|
publicationViewerPopup.style.display = "block";
|
||||||
|
|
||||||
@ -170,12 +176,14 @@ function ShowPublicationViewerWindow(publicationId, event, add){
|
|||||||
|
|
||||||
//Check what action should be listed
|
//Check what action should be listed
|
||||||
if(add){
|
if(add){
|
||||||
publicationAdd.style.display = "block";
|
publicationAdd.style.display = "initial";
|
||||||
publicationDelete.style.display = "none";
|
publicationDelete.style.display = "none";
|
||||||
|
publicationTaskStart.style.display = "none";
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
publicationAdd.style.display = "none";
|
publicationAdd.style.display = "none";
|
||||||
publicationDelete.style.display = "block";
|
publicationDelete.style.display = "initial";
|
||||||
|
publicationTaskStart.style.display = "initial";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -259,15 +267,17 @@ function ShowRunningTasks(event){
|
|||||||
.then(json => {
|
.then(json => {
|
||||||
tagTasksPopupContent.replaceChildren();
|
tagTasksPopupContent.replaceChildren();
|
||||||
json.forEach(task => {
|
json.forEach(task => {
|
||||||
var taskname = document.createElement("footer-tag-task-name");
|
console.log(task);
|
||||||
taskname.innerText = task.publication.sortName;
|
if(task.publication != null){
|
||||||
tagTasksPopupContent.appendChild(taskname);
|
var taskname = document.createElement("footer-tag-task-name");
|
||||||
|
taskname.innerText = task.publication.sortName;
|
||||||
|
tagTasksPopupContent.appendChild(taskname);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
if(json.length > 0){
|
if(tagTasksPopupContent.children.length > 0){
|
||||||
tagTaskPopup.style.display = "block";
|
tagTaskPopup.style.display = "block";
|
||||||
tagTaskPopup.style.left = `${tagTasksRunning.offsetLeft - 20}px`;
|
tagTaskPopup.style.left = `${tagTasksRunning.offsetLeft - 20}px`;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -383,9 +383,6 @@ publication-viewer{
|
|||||||
background-color: var(--accent-color);
|
background-color: var(--accent-color);
|
||||||
border-radius: 5px;
|
border-radius: 5px;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
}
|
|
||||||
|
|
||||||
publication-viewer{
|
|
||||||
padding: 30px;
|
padding: 30px;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -435,22 +432,32 @@ publication-viewer publication-information publication-description {
|
|||||||
overflow-x: scroll;
|
overflow-x: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
publication-viewer publication-information publication-delete {
|
publication-viewer publication-information publication-interactions {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
bottom: 0px;
|
justify-content: end;
|
||||||
right: 0px;
|
align-items: start;
|
||||||
color: red;
|
bottom: 0;
|
||||||
margin: 20px;
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
|
||||||
|
publication-viewer publication-information publication-interactions > * {
|
||||||
|
margin: 0 10px 10px 10px;
|
||||||
font-size: 16pt;
|
font-size: 16pt;
|
||||||
}
|
}
|
||||||
|
|
||||||
publication-viewer publication-information publication-add {
|
publication-viewer publication-information publication-interactions publication-starttask {
|
||||||
position: absolute;
|
color: var(--secondary-color);
|
||||||
bottom: 0px;
|
}
|
||||||
right: 0px;
|
|
||||||
|
publication-viewer publication-information publication-interactions publication-delete {
|
||||||
|
color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
publication-viewer publication-information publication-interactions publication-add {
|
||||||
color: limegreen;
|
color: limegreen;
|
||||||
margin: 20px;
|
|
||||||
font-size: 16pt;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
footer-tag-popup {
|
footer-tag-popup {
|
||||||
|
Reference in New Issue
Block a user