[libsoup/new-directory-list-design] Update directory listing layout
- From: Jan-Michael Brummer <jbrummer src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libsoup/new-directory-list-design] Update directory listing layout
- Date: Fri, 29 May 2020 21:07:02 +0000 (UTC)
commit c52aa66ce4fc81e728704b90abd9ebdf7cba13c2
Author: Jan-Michael Brummer <jan brummer tabos org>
Date: Fri May 29 23:04:17 2020 +0200
Update directory listing layout
Fixes:
- Charset display issues
- Sorting
- Design Update
libsoup/directory.css | 98 +++++++++++++++++++++++++++++++++++
libsoup/directory.js | 72 +++++++++++++++++++++++++
libsoup/meson.build | 7 +++
libsoup/soup-directory-input-stream.c | 64 +++++++++++++++++++----
libsoup/soup-init.c | 2 +
libsoup/soup.gresource.xml | 7 +++
meson.build | 2 +-
po/POTFILES.in | 1 +
8 files changed, 242 insertions(+), 11 deletions(-)
---
diff --git a/libsoup/directory.css b/libsoup/directory.css
new file mode 100644
index 00000000..d10a8f87
--- /dev/null
+++ b/libsoup/directory.css
@@ -0,0 +1,98 @@
+body {
+ color: black;
+ background-color: #f6f5f4;
+}
+
+a {
+ text-decoration: none;
+}
+
+a:hover {
+ text-decoration: underline;
+}
+
+a:visited {
+ color: black;
+}
+
+table {
+ width: 100%;
+ table-layout: fixed;
+}
+
+table[order] > thead > tr > th {
+ cursor: pointer;
+}
+
+table[order] > thead > tr > th::after {
+ display: none;
+ width: .8em;
+ margin-inline-end: -.8em;
+ text-align: end;
+}
+
+table[order="asc"] > thead > tr > th::after {
+ content: "\2193"; /* DOWNWARDS ARROW (U+2193) */
+}
+table[order="desc"] > thead > tr > th::after {
+ content: "\2191"; /* UPWARDS ARROW (U+2191) */
+}
+
+table[order][order-by="0"] > thead > tr > th:first-child > a ,
+table[order][order-by="1"] > thead > tr > th:first-child + th > a ,
+table[order][order-by="2"] > thead > tr > th:first-child + th + th > a {
+ text-decoration: underline;
+}
+table[order][order-by="0"] > thead > tr > th:first-child::after ,
+table[order][order-by="1"] > thead > tr > th:first-child + th::after ,
+table[order][order-by="2"] > thead > tr > th:first-child + th + th::after {
+ display: inline-block;
+}
+
+td {
+ white-space: nowrap;
+ padding: 0;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+/* name */
+th:first-child {
+ padding-inline-end: 2em;
+}
+
+/* size */
+th:first-child + th {
+ padding-inline-end: 1em;
+}
+
+td:first-child + td {
+ text-align: end;
+ padding-inline-end: 1em;
+}
+
+/* date */
+td:first-child + td + td {
+ padding-inline-start: 1em;
+}
+
+th:hover {
+ text-decoration: underline;
+}
+
+#listing {
+ display: flex;
+}
+
+@media (min-width: 550px) {
+ .dialog {
+ padding: 3em;
+ background-color: white;
+ border-radius: 1em;
+ border: 2px solid rgba(211, 215, 207);
+ min-width: 30em;
+ max-width: 65em;
+ margin: 2em auto;
+ }
+}
+
diff --git a/libsoup/directory.js b/libsoup/directory.js
new file mode 100644
index 00000000..8f7c8e96
--- /dev/null
+++ b/libsoup/directory.js
@@ -0,0 +1,72 @@
+
+'use strict';
+
+var gTable, gOrderBy, gTBody, gRows;
+
+document.addEventListener("DOMContentLoaded", function() {
+ gTable = document.getElementsByTagName("table")[0];
+ gTBody = gTable.tBodies[0];
+ if (gTBody.rows.length < 2)
+ return;
+ var headCells = gTable.tHead.rows[0].cells;
+
+ function rowAction(i) {
+ return function(event) {
+ event.preventDefault();
+ orderBy(i);
+ }
+ }
+
+ for (var i = headCells.length - 1; i >= 0; i--) {
+ var anchor = document.createElement("a");
+ anchor.href = "";
+ anchor.appendChild(headCells[i].firstChild);
+ headCells[i].appendChild(anchor);
+ headCells[i].addEventListener("click", rowAction(i), true);
+ }
+ gTable.setAttribute("order", "");
+ orderBy(0);
+}, "false");
+
+function compareRows(rowA, rowB) {
+ var a = rowA.cells[gOrderBy].getAttribute("sortable-data") || rowA.cells[gOrderBy].innerHTML;
+ var b = rowB.cells[gOrderBy].getAttribute("sortable-data") || rowB.cells[gOrderBy].innerHTML;
+ var intA = +a;
+ var intB = +b;
+ if (a == intA && b == intB) {
+ a = intA;
+ b = intB;
+ } else {
+ a = a.toLowerCase();
+ b = b.toLowerCase();
+ }
+ if (a < b)
+ return -1;
+ if (a > b)
+ return 1;
+ return 0;
+}
+
+function orderBy(column) {
+ if (!gRows)
+ gRows = Array.from(gTBody.rows);
+ var order;
+ if (gOrderBy == column) {
+ order = gTable.getAttribute("order") == "asc" ? "desc" : "asc";
+ } else {
+ order = "asc";
+ gOrderBy = column;
+ gTable.setAttribute("order-by", column);
+ gRows.sort(compareRows);
+ }
+ gTable.removeChild(gTBody);
+ gTable.setAttribute("order", order);
+ if (order == "asc")
+ for (var i = 0; i < gRows.length; i++)
+ gTBody.appendChild(gRows[i]);
+ else
+ for (var i = gRows.length - 1; i >= 0; i--)
+ gTBody.appendChild(gRows[i]);
+ gTable.appendChild(gTBody);
+}
+
diff --git a/libsoup/meson.build b/libsoup/meson.build
index 73bb1188..613d68a4 100644
--- a/libsoup/meson.build
+++ b/libsoup/meson.build
@@ -1,6 +1,13 @@
pkg = import('pkgconfig')
+resources = gnome.compile_resources('soup-resources',
+ 'soup.gresource.xml',
+ c_name: 'soup',
+ source_dir: '.'
+)
+
soup_sources = [
+ resources,
'soup-address.c',
'soup-auth.c',
'soup-auth-basic.c',
diff --git a/libsoup/soup-directory-input-stream.c b/libsoup/soup-directory-input-stream.c
index e0ccfd90..ad1818d4 100644
--- a/libsoup/soup-directory-input-stream.c
+++ b/libsoup/soup-directory-input-stream.c
@@ -25,11 +25,12 @@
#include <string.h>
+#include <glib/gi18n-lib.h>
+
#include "soup-directory-input-stream.h"
#include "soup.h"
-#define INIT_STRING "<html>\n<body>\n<table><th align=\"left\">Name</th><th>Size</th><th>Date
Modified</th>\n"
-#define ROW_FORMAT "<td><a href=\"%s\">%s</a></td><td align=\"right\">%s</td><td align=\"right\"
margin=8>%s</td>\n"
+#define ROW_FORMAT "<td><a href=\"%s\">%s</a></td><td align=\"right\" sortable-data=\"%ld\">%s</td><td
align=\"right\" sortable-data=\"%ld\">%s %s</td>\n"
#define EXIT_STRING "</table>\n</html>\n"
G_DEFINE_TYPE (SoupDirectoryInputStream, soup_directory_input_stream, G_TYPE_INPUT_STREAM)
@@ -41,7 +42,9 @@ soup_directory_input_stream_parse_info (SoupDirectoryInputStream *stream,
SoupBuffer *buffer;
GString *string;
const char *file_name;
- char *escaped, *path, *xml_string, *size, *time;
+ char *escaped, *path, *xml_string, *size, *date, *time;
+ goffset raw_size;
+ gint64 timestamp;
#if !GLIB_CHECK_VERSION (2, 61, 2)
GTimeVal modified;
#endif
@@ -62,21 +65,25 @@ soup_directory_input_stream_parse_info (SoupDirectoryInputStream *stream,
xml_string = g_markup_escape_text (file_name, -1);
escaped = g_uri_escape_string (file_name, NULL, FALSE);
path = g_strconcat (stream->uri, G_DIR_SEPARATOR_S, escaped, NULL);
- size = g_format_size (g_file_info_get_size (info));
+ raw_size = g_file_info_get_size (info);
+ size = g_format_size (raw_size);
#if GLIB_CHECK_VERSION (2, 61, 2)
modification_time = g_file_info_get_modification_date_time (info);
#else
g_file_info_get_modification_time (info, &modified);
modification_time = g_date_time_new_from_timeval_local (&modified);
#endif
- time = g_date_time_format (modification_time, "%X %x");
+ time = g_date_time_format (modification_time, "%X");
+ date = g_date_time_format (modification_time, "%x");
+ timestamp = g_date_time_to_unix (modification_time);
g_date_time_unref (modification_time);
- g_string_append_printf (string, ROW_FORMAT, path, xml_string, size, time);
+ g_string_append_printf (string, ROW_FORMAT, path, xml_string, raw_size, size, timestamp, time, date);
g_string_append (string, "</tr>\n");
buffer = soup_buffer_new (SOUP_MEMORY_TAKE, string->str, string->len);
g_free (time);
+ g_free (date);
g_free (escaped);
g_free (size);
g_free (path);
@@ -190,12 +197,48 @@ soup_directory_input_stream_class_init (SoupDirectoryInputStreamClass *stream_cl
inputstream_class->close_fn = soup_directory_input_stream_close;
}
+static
+char *soup_directory_input_stream_create_header (SoupDirectoryInputStream *stream)
+{
+ char *header;
+ GBytes *css = g_resources_lookup_data ("/org/gnome/libsoup/directory.css",
G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
+ GBytes *js = g_resources_lookup_data ("/org/gnome/libsoup/directory.js",
G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
+
+ header = g_strdup_printf ("<html><head>" \
+ "<title>%s</title>" \
+ "<meta http-equiv=\"Content-Type\" content=\"text/html;\" charset=\"UTF-8\">" \
+ "<style>%s</style>" \
+ "<script>%s</script>" \
+ "</head>" \
+ "<body>" \
+ "<div id=\"listing\">" \
+ "<div class=\"dialog\">" \
+ "<table id=\"table\">" \
+ "<thead>" \
+ "<th align=\"left\">%s</th><th align=\"right\">%s</th><th
align=\"right\">%s</th>" \
+ "</thead>",
+ stream->uri,
+ css ? (gchar *)g_bytes_get_data (css, NULL) : "",
+ js ? (gchar *)g_bytes_get_data (js, NULL) : "",
+ _("Name"),
+ _("Size"),
+ _("Date Modified"));
+ return header;
+}
+
static void
soup_directory_input_stream_init (SoupDirectoryInputStream *stream)
{
- stream->buffer = soup_buffer_new (SOUP_MEMORY_STATIC,
- INIT_STRING,
- sizeof (INIT_STRING));
+}
+
+static void
+soup_directory_input_stream_setup_buffer (SoupDirectoryInputStream *stream)
+{
+ char *init = soup_directory_input_stream_create_header (stream);
+
+ stream->buffer = soup_buffer_new (SOUP_MEMORY_TAKE,
+ init,
+ strlen (init));
}
GInputStream *
@@ -212,6 +255,7 @@ soup_directory_input_stream_new (GFileEnumerator *enumerator,
SOUP_DIRECTORY_INPUT_STREAM (stream)->enumerator = g_object_ref (enumerator);
SOUP_DIRECTORY_INPUT_STREAM (stream)->uri = soup_uri_to_string (uri, FALSE);
+ soup_directory_input_stream_setup_buffer (SOUP_DIRECTORY_INPUT_STREAM (stream));
+
return stream;
}
-
diff --git a/libsoup/soup-init.c b/libsoup/soup-init.c
index c4950ced..31059f79 100644
--- a/libsoup/soup-init.c
+++ b/libsoup/soup-init.c
@@ -19,6 +19,8 @@
HMODULE soup_dll;
#endif
+#include <locale.h>
+
static void
soup_init (void)
{
diff --git a/libsoup/soup.gresource.xml b/libsoup/soup.gresource.xml
new file mode 100644
index 00000000..da3ad10b
--- /dev/null
+++ b/libsoup/soup.gresource.xml
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<gresources>
+ <gresource prefix="/org/gnome/libsoup">
+ <file>directory.css</file>
+ <file>directory.js</file>
+ </gresource>
+</gresources>
diff --git a/meson.build b/meson.build
index fffbb42f..b5aaff2b 100644
--- a/meson.build
+++ b/meson.build
@@ -361,7 +361,7 @@ prefix = get_option('prefix')
cdata.set_quoted('PACKAGE_VERSION', soup_version)
cdata.set_quoted('LOCALEDIR', join_paths(prefix, get_option('localedir')))
-cdata.set_quoted('GETTEXT_PACKAGE', libsoup_api_name)
+cdata.set_quoted('GETTEXT_PACKAGE', meson.project_name())
configure_file(output : 'config.h', configuration : cdata)
subdir('libsoup')
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 3cd20bf4..61d52750 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -1,5 +1,6 @@
libsoup/soup-body-input-stream.c
libsoup/soup-cache-input-stream.c
+libsoup/soup-directory-input-stream.c
libsoup/soup-converter-wrapper.c
libsoup/soup-message-client-io.c
libsoup/soup-message-io.c
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]