Commit graph

68 commits

Author SHA1 Message Date
Michael Demetriou
6cca097de0 Needs testing: frontend (javascript) code for image uploads.
I was trying to create the image upload functionality of *writefreely*. The spec said that after the user drops an image on the textarea a markdown image placeholder should appear `[image](file.png)`, just like it happens on [discourse](https://www.discourse.org/).

However there were a few challenges. *Writefreely* is a blogging platform, not a forum, so longer texts are possible, if not common. Appending the markdown at the end of the text, especially if the text overflows the viewport is bad user interface as the user will have no confirmation whether his action had a result or not (the text would have been appended off-screen). Also, in blog posts we often append larger images which take some time to upload, so a progress indicator would be useful.

Another challenge was multiple uploads. Since additional markup isn't allowed inside the textarea I had to find a way to update the right markdown block when the respective file upload updates or finishes.

Lastly the default action when one hovers a file over a textarea, the browser insinuates that the file will be dropped in a specific place under the mouse cursor by showing a text cursor in the text. However it doesn't give the developers any way to know where that text will be dropped. It does drop the local `file://` URI however so we can replace that with our markdown. What if the user had the same `file://` uri elsewhere in the text, however? Perhaps he was writing about including local files in markdown documents.

The above function does not work reliably in Chrome on GNOME. Sometimes it inserts the `file://` URI under the cursor and sometimes it navigates to the image directly. So I'll probably have to browser-sniff there (bad, I know)

So the solution had to deal with the following stuff:

1. Insert the image in the last editing position unless the browser allows you to drop at a specific place
2. If the browser allows you to drop at a specific place, do it.
3. Update the markdown with progress and when the upload is done go replace the loading thing with the remote filename the server returned

This is simple. You can use `textarea.selectionStart` and `textarea.selectionEnd` to get the selection index (if text is selected) or the cursor position if these two values are equal. If text is selected replace with the dropped image.

This was not so simple and despite being able to create a [demo](http://qwazix.com/shared/firefox%20dropping%20in%20place.webm) this did not work for more than one files (this is fixable) nor it could work in chrome (this doesn't seem fixable, chrome sometimes drops the `file://` URI in the textarea and others navigates to it). Thus I'm inclined to drop this functionality as the code for it is dirty anyway. [And then I found out that this doesn't work on Windows/MacOS so yeah...][Now I have dropped this]

<video><source src="http://qwazix.com/shared/firefox%20dropping%20in%20place.webm" type="video/webm"></video>

However I'd like to talk about my solution: in the drop event `textarea.value` still holds the text without the `file://` URI. However ten milliseconds later the text has already updated. Here's why the dirty code: a `setTimeout({...},10)` that allow us to get to the updated text. We can then iterate over all the occurrences of `file://.*?/filename.ext` and check if they exist in the previous text. If we find one that doesn't then we can replace that with our markdown. This is the code:

``` javascript
        function insertTextAtDropPoint(text, textarea, filename){
            if (textarea.nodeName == "TEXTAREA") {
                // save cursor position so that we can set it
                // back after the operation on value
                var startingPosition = textarea.selectionStart;
                var rxp = new RegExp('file://.*?/'+filename);
                console.log(rxp);
                textarea.value = replaceNewPatternInString(rxp, oldtext, textarea.value, text);
                // set the cursor to its original position
                textarea.selectionStart = textarea.selectionEnd = startingPosition + text.length;
            } else throw "Element is not a textarea"
        }

function replaceNewPatternInString(pattern, oldstring, newstring, replacement){
            var index = 0;
            do {
                // find first occurence of pattern
                var match = newstring.substr(index, newstring.length).match(pattern);
                index += match.index;
                // take the part of the string from the beginning until
                // the end of the pattern
                // and check if you can find it in the old string
                // if you can go to the next occurence of the pattern
                // until you find one
                // that doesn't exist in the old string.
                index += match[0].length;
            } while (oldstring.indexOf(newstring.substr(0, index)) != -1);
            return newstring.substr(0,index-match[0].length) + replacement + newstring.substr(index,newstring.length);
        }
```

Still, believing that the file will be dropped under the cursor (which is probably the user's expectation when they see the moving **I** cursor) and then have it dropped in the last edit position is not good UX. Chrome disables that animation if you `preventDefault()` on `dragover` but Firefox does not so I'll have to resort to using `pointer-events` to disable that functionality. [Update: it looks like doing `preventDefault()` on `dragenter` resolves this nicely]

We don't have additional markup inside the textarea so if the user drops multiple files we need to know which one to update when the upload progresses or finishes. *Discourse* solves this by using filenames and appending numbers to them if it finds the same filename being already used. I decided that creating a temporary hash is simpler so I prepend one before each filename, making the markdown unique. Then it's a matter of search and replace to update progress.

Replacing text in the textarea entails getting the contents, changing them in javascript and putting them back in. This causes the spellcheck to fire again creating a subtle flicker in the wavy red lines. I was testing with *lorem ipsum* which has wavy red lines everywhere and that flicker quickly became annoying. Updating the progress every 5, or even 10% makes that annoyance a lot less noticeable and I suspect that in regular text with much less misspelled words this will not be an issue.

Finally, after each change we also need to put the cursor back to where it was because updating `textarea.value` sets the cursor to the end.

This was surprisingly easy. I just copied everything into `pad.tmpl` and it (almost) just worked. I had to point the `xhr` endpoint to my `upload.php` test file and enable **CORS** there but this was trivial.

 ## Backend

Next step: backend image handling.

Also posted here: https://mixt.qwazix.com/d/naac7l07tr
Individual commits while I developed this: https://github.com/qwazix/minimalist-ajax-upload/commits/dragDrop
2019-07-12 15:03:19 +03:00
Matt Baer
ad6fd5e809 Use "Draft" in post meta page
instead of "Anonymous".
2019-07-01 19:59:52 -04:00
Matt Baer
554995916e Replace top-left "w" button on post meta page
This was still a relic of Write.as. Now it has the same icon as the
WriteFreely editor.
2019-07-01 19:56:50 -04:00
Matt Baer
7aaff778da
Merge pull request #123 from writeas/private-instance
Private instances

Resolves T576
2019-07-01 19:14:20 -04:00
Matt Baer
fdcdfe4d25 Open landing page preview in new window 2019-07-01 19:05:47 -04:00
Matt Baer
a72ce2ef29 Make landing page dynamic
This enables admins to customize their landing / home page via the Admin
dashboard -- including the text at the top of the page and the section
below it. It keeps the current default text, falling back to it if the
user hasn't overwritten it.

Ref T565
2019-06-27 17:06:37 -04:00
Michael Demetriou
4feac6dcd2 Remove langs list from post-render as it does not actually
do anything useful (see https://github.com/writeas/writefreely/pull/128#issuecomment-506207107)
2019-06-27 18:15:58 +03:00
Michael Demetriou
0842119694 Change sh alias back to bash
because this is the alias in highlight itself.

(see https://github.com/writeas/writefreely/pull/128#issuecomment-505766645)
2019-06-27 00:12:18 +03:00
Michael Demetriou
c2d7c2c8b7 Fix #124 according to the snippet by @mrvdb
I changed the sh alias to shell instead of bash.

The additions to the `highlight(nodes)` function look redundant.
It works for me without them but maybe they cover an edge case I
cannot think about?
2019-06-25 21:17:30 +03:00
Matt Baer
35718cd239 Change blog visibility explanations on Private instance
Ref T576
2019-06-16 20:30:56 -04:00
Matt Baer
bf989eb696 Hide Reader link on private instance when unauth'd
Ref T576
2019-06-16 20:29:31 -04:00
Matt Baer
161f7a8de2 Support changing landing conf val from Admin UI
Closes T651
2019-06-16 17:38:34 -04:00
Matt Baer
b9b41b1ef7 Enable un-setting RTL setting via web
Previously, once RTL was enabled on a post, you couldn't unset it via
the web application. This fixes that. (Fixes #103)
2019-05-18 23:16:42 -04:00
Matt Baer
e80f99a72e Fix draft post metadata
Previously it referenced an image on write.as and had the incorrect
og:url property. This also fixes the canonical URL on single-user
instances. Closes #91
2019-04-12 14:56:46 -04:00
Matt Baer
238a913ce3 Make WriteFreely spacing consistent 2019-04-11 21:33:33 -04:00
Matt Baer
63a2225b7f Add admin dashboard link to dropdown navs 2019-04-11 21:11:30 -04:00
Matt Baer
af0f6302a2 Replace --reset-pass instructions with admin guide link 2019-04-11 21:10:45 -04:00
Matt Baer
9cb0f80921 Support changing instance page titles
Now admins can choose a title for their About and Privacy pages; now
editable through the instance page editor.

This adds `title` and `content_type` fields to the `appcontent` table,
requiring a migration by running `writefreely --migrate`

The content_type field specifies that items we're currently storing in
this table are all "page"s; queries for fetching these have been updated
to filter for this type. In the future, this field will be used to
indicate when an item is a stylesheet (ref T563) or other supported
type.

Ref T566
2019-04-11 13:56:07 -04:00
Matt Baer
4cad074b44 Link to version-specific writer's guide 2019-04-11 13:52:10 -04:00
Matt Baer
a850fa14cd Move instance page editing to dedicated section
This adds a "Pages" section to the admin part of the site, and enables
admins to edit the pre-defined About and Privacy pages there, instead of
on the dashboard itself.

It also restructures how these pages get sent around in the backend and
lays the groundwork for dynamically adding static pages. The backend
changes were made with more customization in mind, such as an
instance-wide custom stylesheet (T563).

Ref T566
2019-04-06 13:23:22 -04:00
Matt Baer
09fb73bdd5 Standardize admin navigation 2019-04-06 11:15:14 -04:00
Marcel van der Boom
f40ce14fb2 Resolve an edge case where last language has error
If there are multiple language blocks on a page, we set the
onload on the last one to load all highlighting at once.

If the last language block has an error, the onload would
never fire and thus all blocks would not be highlighted.

The simplest resolution is to fire the callback regardless. We've
already loaded everything so running the callback is not causing any
performance hit which is relevant I think.
2019-03-05 14:36:40 +01:00
Matt Baer
99489aa920 Change zip link to txt on Export page
"zip" doesn't really describe what the posts themselves are exported as.
"txt" does.
2019-02-25 15:49:11 -05:00
Matt Baer
c2436a43c5 Merge branch 'master' into develop 2019-02-04 10:14:59 +01:00
Matt Baer
a896d475e4 Clean up resource URLs on collection-tags template
This included files.writeas.org paths and other Write.as-specific logic.
2019-02-04 10:12:38 +01:00
Matt Baer
d8876058a6 Add WriteFreely version to admin dash 2019-01-18 11:33:57 -05:00
Matt Baer
70e823d6ab Support user invites
This includes:

- A new `user_invites` config value that determines who can generate
  invite links
- A new page for generating invite links, with new user navigation link
- A new /invite/ path that allows anyone to sign up via unique invite
  link, even if registrations are closed
- Tracking who (of registered users) has been invited by whom

It requires an updated database with `writefreely --migrate` in order to
work.

This closes T556
2019-01-18 00:05:50 -05:00
Matt Baer
bf7d422039 Add pager to admin user list
This enables paging through the entire list of users.

Ref T553
2019-01-05 09:37:53 -05:00
Matt Baer
0e722de82c Add admin user list
This enables admins on multi-user instances to see all users registered,
and view the details of each, including:

- Username
- Join date
- Total posts
- Last post date
- All blogs
  - Public info
  - Views
  - Total posts
  - Last post date
  - Fediverse followers count

This is the foundation for future user moderation features.

Ref T553
2019-01-04 22:28:29 -05:00
Matt Baer
e525bc32a7 Use language-specific dash in post titles
This closes #1
2018-12-24 13:58:32 -05:00
Matt Baer
25a68d0c0e Add Reader section
This adds a "Reader" section of the site for admins who want to enable
it for their instance. That means visitors can go to /read and see who
has publicly shared their writing. They can also follow all public posts
via RSS by going to /read/feed/. Writers on an instance with this
`local_timeline` setting enabled can publish to the timeline by going
into their blog settings and choosing the "Public" visibility setting.

The `local_timeline` feature is disabled by default, as is the Public
setting on writer blogs. Enabling it adds a "Reader" navigation item and
enables the reader endpoints. This feature will also consume more
memory, as public posts are cached in memory for 10 minutes.

These changes include code ported over from Read.Write.as, and thus
include some experimental features like filtering public posts by tags
and authors. These features aren't well-tested or complete.

Closes T554
2018-12-10 16:08:07 -05:00
Matt Baer
9e466a6d23 Locally host MathJax
This closes T551
2018-12-07 16:50:29 -05:00
Matt Baer
860e8c0120 Locally host highlightjs
Part of T551
2018-12-07 16:37:14 -05:00
Matt Baer
8cbc02d7cf Hide unneeded config values in single-user mode
(in the admin UI.)
2018-12-03 18:45:55 -05:00
Matt Baer
cbf6ff54df Add site_description config value
This changes what displays in the NodeInfo, and in the future might be
used for other things.
2018-12-03 18:36:33 -05:00
Matt Baer
573ce02739 Remove params from URL after loading admin panel
This ensures that refreshing the page doesn't include any past success /
failure messages.
2018-12-03 18:34:36 -05:00
Matt Baer
d2f89c6360 Open pages linked from admin UI in new window 2018-12-03 17:34:57 -05:00
Matt Baer
9fe4b09de5 Support editing some config values in admin UI
This is almost all of T541
2018-12-03 17:30:31 -05:00
Matt Baer
09a3fe09fe
Merge pull request #39 from mrvdb/codehighlight
Codehighlight, add support for all languages
2018-12-03 12:24:36 -05:00
Matt Baer
5fc41687be Fix whitespace 2018-12-03 12:18:04 -05:00
Matt Baer
fc856e36eb Fix editing metadata on single-user instances
This closes #40
2018-12-01 16:27:14 -05:00
Marcel van der Boom
3b4d14f194 Only push language uri once on load stack 2018-11-29 17:36:50 +01:00
Marcel van der Boom
c6e4967728 Add support for all languages
- dynamically construct a list of languages to load
- fire hightlighting once last file has loaded
2018-11-29 16:25:53 +01:00
Matt Baer
3dd6e34914 Fix whitespace in templates 2018-11-23 12:42:30 -05:00
Matt Baer
2b5e869916 Rename render.tmpl to post-render.tmpl 2018-11-23 12:37:59 -05:00
Matt Baer
246a6dc554 Fix whitespace in highlight JS 2018-11-23 12:37:59 -05:00
Marcel van der Boom
a54f5fc9d8 Fix typos 2018-11-22 16:03:44 +01:00
Marcel van der Boom
d63db27917 Merge remote-tracking branch 'upstream/master' into codehighlight
* upstream/master:
  Work as a standalone server, including TLS
  Include About/Privacy page content in page description
  Show instance stats on About page
  Change default database name to writefreely
  Use and validate database type before connecting
  Mention Contributing Guide in README
  Add AUTHORS.md
  Fix About page link in Admin dash
  Include version in archives made by `make release`
  Remove keys.sh from make release
  Add make release
2018-11-22 15:09:58 +01:00
Marcel van der Boom
e400fe1649 Only load highlght css when needed 2018-11-22 15:01:11 +01:00
Marcel van der Boom
add06ee56c Only load js when there are blocks to highlight
Crux was the load event for the script tag inserted.
2018-11-22 14:31:25 +01:00