Compare commits
15 Commits
896fdd6443
...
7f220a7e68
Author | SHA1 | Date |
---|---|---|
Kaan Barmore-Genç | 7f220a7e68 | |
Kaan Barmore-Genç | 69bdc6abf8 | |
Kaan Barmore-Genç | 31e61be4b1 | |
Kaan Barmore-Genç | 8584ba7f94 | |
Kaan Barmore-Genç | 39a0a6499b | |
Kaan Barmore-Genç | 7282c0019d | |
Kaan Barmore-Genç | 5ef4166af3 | |
Kaan Barmore-Genç | 962973d869 | |
Kaan Barmore-Genç | 0da03b6b03 | |
Kaan Barmore-Genç | 59fb8f957d | |
Kaan Barmore-Genç | 6b1133b4d4 | |
Kaan Barmore-Genç | ec0ca8cab8 | |
Kaan Barmore-Genç | 534578b8ba | |
Kaan Barmore-Genç | 6e73404713 | |
Kaan Barmore-Genç | 68bdee4bbb |
|
@ -1,3 +1,5 @@
|
|||
.clj-kondo
|
||||
.lsp
|
||||
.calva
|
||||
.calva
|
||||
gemini
|
||||
docs
|
||||
|
|
|
@ -0,0 +1,32 @@
|
|||
# This makefile builds the website to be published.
|
||||
# For the HTTP/HTML portion, that's pushed to Github pages.
|
||||
# For the gemini portion, that's also pushed to my gemini server by this makefile.
|
||||
source_files := $(shell find content/*.md)
|
||||
target_files := $(patsubst content/%.md,gemini/%.gmi,$(source_files))
|
||||
|
||||
.PHONY: default
|
||||
default: build-gemini publish-gemini build-html
|
||||
|
||||
gemini/%.gmi: content/%.md
|
||||
lowdown -tgemini $< > $@
|
||||
|
||||
gemini/index.gmi: $(source_files)
|
||||
for file in $(target_files) ; do \
|
||||
echo "=> $$file" | sed 's/gemini//' >> gemini/index.gmi ; \
|
||||
done
|
||||
|
||||
.PHONY: build-gemini
|
||||
build-gemini: $(target_files) gemini/index.gmi
|
||||
cp gemini/_index.gmi gemini/index.gmi
|
||||
|
||||
.PHONY: build-html
|
||||
build-html:
|
||||
boot publish
|
||||
|
||||
.PHONY: clean
|
||||
clean:
|
||||
echo ${target_files}
|
||||
|
||||
.PHONY: publish
|
||||
publish-gemini: ${target_files}
|
||||
rsync -av content/img content/extra gemini/index.gmi $^ gemini.bgenc.net:/var/gemini/
|
|
@ -0,0 +1,117 @@
|
|||
---
|
||||
title: Solving `app_data` or `ReqData` missing in requests for actix-web
|
||||
date: 2022-03-26
|
||||
---
|
||||
|
||||
> This post is day 5 of me taking part in the
|
||||
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
|
||||
|
||||
I'm using `actix-web` to set up a web server, and I've been hitting a small
|
||||
problem that I think other people may come across too.
|
||||
|
||||
To explain the problem, let me talk a bit about my setup. I have a custom
|
||||
middleware that checks if a user is authorized to access a route. It looks like
|
||||
this:
|
||||
|
||||
```rust
|
||||
impl<S: 'static, B> Service<ServiceRequest> for CheckLoginMiddleware<S>
|
||||
where
|
||||
S: Service<ServiceRequest, Response = ServiceResponse<B>, Error = Error>,
|
||||
S::Future: 'static,
|
||||
{
|
||||
type Response = ServiceResponse<EitherBody<B>>;
|
||||
type Error = Error;
|
||||
type Future = LocalBoxFuture<'static, Result<Self::Response, Self::Error>>;
|
||||
|
||||
dev::forward_ready!(service);
|
||||
|
||||
fn call(&self, req: ServiceRequest) -> Self::Future {
|
||||
let state = self.state.clone();
|
||||
let (request, payload) = req.into_parts();
|
||||
let service = self.service.clone();
|
||||
|
||||
let user_token = get_token_from_header(&request);
|
||||
let path_token = if self.allow_path_tokens {
|
||||
get_token_from_query(&request)
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
Box::pin(async move {
|
||||
match verify_auth(state, user_token, path_token, request.path()).await {
|
||||
Ok(authorized) => {
|
||||
tracing::debug!("Request authorized, inserting authorization token");
|
||||
// This is the "important bit" where we insert the authorization token into the request data
|
||||
request.extensions_mut().insert(authorized);
|
||||
let service_request =
|
||||
service.call(ServiceRequest::from_parts(request, payload));
|
||||
service_request
|
||||
.await
|
||||
.map(ServiceResponse::map_into_left_body)
|
||||
}
|
||||
Err(err) => {
|
||||
let response = HttpResponse::Unauthorized().json(err).map_into_right_body();
|
||||
|
||||
Ok(ServiceResponse::new(request, response))
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The `verify_auth` function is omitted, but the gist of it is that it returns an `Result<Authorized, Error>`.
|
||||
If the user is authorized, the authorization token `verify_auth` returned is then attached to the request.
|
||||
|
||||
Then here's how I use it in a path:
|
||||
|
||||
```rust
|
||||
#[delete("/{store}/{path:.*}")]
|
||||
async fn delete_storage(
|
||||
params: web::Path<(String, String)>,
|
||||
// This parameter is automatically filled with the token
|
||||
authorized: Option<ReqData<Authorized>>,
|
||||
) -> Result<HttpResponse, StorageError> {
|
||||
let (store, path) = params.as_ref();
|
||||
|
||||
let mut store_path = get_authorized_path(&authorized, store)?;
|
||||
store_path.push(path);
|
||||
if fs::metadata(&store_path).await?.is_file() {
|
||||
tracing::debug!("Deleting file {:?}", store_path);
|
||||
fs::remove_file(&store_path).await?;
|
||||
} else {
|
||||
tracing::debug!("Deleting folder {:?}", store_path);
|
||||
fs::remove_dir(&store_path).await?;
|
||||
}
|
||||
Ok(HttpResponse::Ok().finish())
|
||||
}
|
||||
```
|
||||
|
||||
This setup worked for this path, but would absolutely not work for another path.
|
||||
I inserted logs to track everything, and just found that the middleware would
|
||||
insert the token, but the path would just get `None`. How‽ I tried to slowly
|
||||
strip everything away from the non-functional path until it was identical to
|
||||
this one, but it still would not work.
|
||||
|
||||
Well it turns out the solution was very simple, see this:
|
||||
|
||||
```rust
|
||||
use my_package::storage::put_storage;
|
||||
use crate::storage::delete_storage;
|
||||
```
|
||||
|
||||
Ah! They are imported differently. I had set up my program as both a library and
|
||||
a program for various reasons. However, it turns out importing the same thing
|
||||
from `crate` is different from importing it from the library. Because of the
|
||||
difference in import, Actix doesn't recognize that the types match, so the route
|
||||
can't access the attached token.
|
||||
|
||||
The solution is normalizing the imports. I went with going through the library
|
||||
for everything, because that's what `rust-analyzer`s automatic import seems to
|
||||
prefer.
|
||||
|
||||
```rust
|
||||
use my_package::storage::{put_storage, delete_storage};
|
||||
```
|
||||
|
||||
Solved!
|
|
@ -0,0 +1,35 @@
|
|||
---
|
||||
title: "Black Crown Initiate"
|
||||
date: 2022-04-02
|
||||
---
|
||||
|
||||
> This post is day 9 of me taking part in the
|
||||
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
|
||||
|
||||
I love metal, I've been listening to metal since I was 13. It was the first
|
||||
music genre that I actually liked: until I discovered metal I actually thought I
|
||||
didn't like music at all, because nothing I heard on the radio or heard my
|
||||
friends listening to were interesting to me. My taste in music has expanded and
|
||||
changed over the years to include different types of music and genres, but metal
|
||||
remains the one I love the most.
|
||||
|
||||
Demonstrating my metal-worthiness aside, I've always listened to European metal
|
||||
bands. I had this weird elitist thought that "good" metal could only come from
|
||||
Europe, with exceptions for some non-European bands, and that American metal was
|
||||
just always bad. This is obviously false, but I just had never came across
|
||||
anything American that I had liked. That's until recently.
|
||||
|
||||
I recently came across [Black Crown Initiate](https://www.metal-archives.com/bands/Black_Crown_Initiate/3540386765),
|
||||
a progressive death metal band from Pennsylvania. And I have to tell you that they are amazing.
|
||||
|
||||
Their first release "Song of the Crippled Bull" is absolutely amazing. The music
|
||||
is just the right amount of metal and progressive, and lyrics are amazing. The
|
||||
clean vocals get the themes of the song across, while the growls give a lot of
|
||||
power to the songs. My favorite songs from this release are "Stench of the Iron
|
||||
Age" and the title track "Song of the Crippled Bull". Other hightlights from the
|
||||
band I've listened to so far include "A Great Mistake", "Death Comes in
|
||||
Reverse", "Vicious Lives".
|
||||
|
||||
I'm still making my way through their songs, but I'm glad to have discovered
|
||||
something from America that I absolutely love. I'm now trying to find more
|
||||
non-European bands that I enjoy.
|
|
@ -0,0 +1,56 @@
|
|||
---
|
||||
title: An introduction to Bulgur Cloud - simple self hosted cloud storage
|
||||
date: 2022-03-29
|
||||
---
|
||||
|
||||
> This post is day 8 of me taking part in the
|
||||
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
|
||||
|
||||
I've been recently working on Bulgur Cloud, a self hosted cloud storage
|
||||
software. It's essentially Nextcloud, minus all the productivity software. It's
|
||||
also designed to be much simpler, using no databases and keeping everything on
|
||||
disk.
|
||||
|
||||
The software is still too early to actually demo, but the frontend is at a point
|
||||
where I can show some features off. So I wanted to show it off.
|
||||
|
||||
![The login screen](/img/2022-03-29-00-17-38.png)
|
||||
|
||||
I've been going for a clean "print-like" look. I think it's going pretty well so far.
|
||||
|
||||
![The directory listing](/img/2022-03-29-00-16-13.png)
|
||||
|
||||
I'm not sure about the details of how the directory listing will look. I don't
|
||||
think I like the upload button in the corner, and the rename and delete icons
|
||||
feel like they would be easy to mis-press. There is a confirmation before
|
||||
anything is actually deleted, but it still would be annoying.
|
||||
|
||||
![Delete confirmation prompt](/img/2022-03-29-00-20-48.png)
|
||||
|
||||
Something I'm pretty happy with is the file previews. I've added support for
|
||||
images, videos, and PDFs. Video support is restricted by whatever formats are
|
||||
supported by your browser, the server doesn't do any transcoding, but I think
|
||||
it's still very useful for a quick preview. I'm also planning on support for
|
||||
audio files. The server supports range requests, so you can seek around in the
|
||||
video without waiting to download everything (although I've found that Firefox
|
||||
doesn't handle that very well).
|
||||
|
||||
![Video file preview](/img/2022-03-29-00-22-48.png)
|
||||
|
||||
This is a web interface only so far, but I'm planning to add support for mobile
|
||||
and desktop apps eventually. I've been building the interface with React Native
|
||||
so adding mobile/desktop support shouldn't be too difficult, but I've been
|
||||
finding that "write once, run everywhere" isn't always that simple. I ended up
|
||||
having to add web-only code to support stuff like the video and PDF previews, so
|
||||
I'll have to find replacements for some parts. Mobile and desktop apps natively
|
||||
support more video and audio formats too, and with native code you usually have
|
||||
the kind of performance to transcode video if needed.
|
||||
|
||||
The backend is written in Rust with `actix-web`, using async operations. It's
|
||||
incredibly fast, and uses a tiny amount of resources (a basic measurement
|
||||
suggests < 2 MB of memory used). I'm pretty excited about it!
|
||||
|
||||
After a few more features (namely being able to move files), I'm planning to put
|
||||
together a demo to show this off live! The whole thing will be open source, but
|
||||
I'm waiting until it's a bit more put together before I make the source public.
|
||||
The source will go live at the same time as the demo.
|
|
@ -0,0 +1,79 @@
|
|||
---
|
||||
title: Do kids not know computers now?
|
||||
date: 2022-03-28
|
||||
---
|
||||
|
||||
> This post is day 7 of me taking part in the
|
||||
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
|
||||
|
||||
|
||||
One discussion point I've seen around is that kids nowadays don't know how to
|
||||
use computers. Okay that's a bit of a strawman, but this article titled [File Not Found](https://www.theverge.com/22684730/students-file-folder-directory-structure-education-gen-z).
|
||||
|
||||
The gist of the article is that Gen-Z kids are too used to search interfaces.
|
||||
That means they don't actually know about where files are stored, or how they
|
||||
are organized. They only know that they can access the files by searching for
|
||||
them. The article talks about how professors ended up having to teach them how
|
||||
to navigate directory structures and file extensions.
|
||||
|
||||
As the article claims, it seems to be related to how modern user interfaces are
|
||||
designed. Our UIs nowadays are more focused around search capabilities: you just
|
||||
type in a search bar and find what you need.
|
||||
|
||||
![bemenu, displaying a partial search and several matching applications.](/img/app-search-bar.png)
|
||||
|
||||
In some sense I do like this sort of interface. I use something like that when
|
||||
launching applications, both on my Desktop and on my laptop! It's actually a
|
||||
better interface compared to hunting for icons on your desktop. I use similar
|
||||
interfaces in VSCode to switch between open editor tabs.
|
||||
|
||||
However, this is a complimentary interface to hierarchy and organization. Going
|
||||
back to the file systems example discussed in the article, being able to search
|
||||
through your files and folders is useful. But it's not a replacement for
|
||||
hierarchy. You can't just throw files into a folder, and expect to always find
|
||||
them accurately.
|
||||
|
||||
Let me give an example with Google Photos. I have been keeping all my photos on
|
||||
Google Photos, and between migrating photos from old phones and ones I have
|
||||
taken on new phones, I have over 8,000 photos. This is completely disorganized
|
||||
of course, but Google Photos has a search functionality. It even uses AI to
|
||||
recognize the items in the photos, which you can use in the search. A search for
|
||||
"tree" brings up photos of trees, "cat" brings up cats, and you can even tag
|
||||
people and pets and then search for their names. Very useful, right?
|
||||
|
||||
Well, it is sometimes. I recently had to remember what my wife's car license
|
||||
plate is. A quick search for "license plate" on google photos and luckily, I had
|
||||
taken a photo of her car that included the license plate in the frame. Success!
|
||||
On the other hand, I was trying to find some photos from a particular gathering
|
||||
with my friends. Searches for their names, names of the place, or stuff I know
|
||||
are in the picture turned up with nothing. I eventually had to painstakingly
|
||||
scroll through all photos to find the one I wanted.
|
||||
|
||||
This reminds me of 2 things. One is this article named [To Organize The World's
|
||||
Information](https://dkb.io/post/organize-the-world-information) by
|
||||
[@dkb868@twitter.com](https://nitter.net/dkb868). One thing I found interesting
|
||||
on that article was that the concept of "the library" has been lost over the
|
||||
last few decades as a way to organize information. They define the library as a
|
||||
hierarchical, categorized directory of information. The article also talks about
|
||||
other organizational methods, and is worth a read.
|
||||
|
||||
The other thing is the note taking software we're building at my workplace,
|
||||
[Dendron](https://dendron.so/). One of the core tenets of Dendron is that the
|
||||
information is hierarchical. Something the founder Kevin recognizes was that
|
||||
other note taking software make it easier to make new notes, but they don't
|
||||
support hierarchical structures which makes it hard to find those notes later.
|
||||
I've also experienced this, when I used other note taking software (or sticky
|
||||
notes!) I found that it was easy to just jot down a few notes, but they very
|
||||
quickly get lost or hard to find when you need them. A hierarchical organization
|
||||
makes it possible to actually find and reference the information later.
|
||||
|
||||
Requiring organization creates a barrier of entry to storing information, but
|
||||
what good is storing information if you can't retrieve the information later?
|
||||
This seems to work pretty well with Dendron. Would it not work for other things?
|
||||
Why not for taking photos? You of course want to be able to quickly snap a photo
|
||||
so you can record a moment before it's gone, but perhaps you could be required
|
||||
to organize your photos afterwards. Before modern cellphones & internet
|
||||
connected cameras, you'd have to get your photos developed or transfer them off
|
||||
an SD card: a step where you would have to (or have the opportunity to) organize
|
||||
your photos. I wonder if we cloud services could ask you to organize your photos
|
||||
before syncing them as well.
|
Binary file not shown.
After Width: | Height: | Size: 18 KiB |
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
Binary file not shown.
After Width: | Height: | Size: 248 KiB |
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
|
@ -10,3 +10,6 @@ page](https://github.com/SeriousBug).
|
|||
|
||||
I published several papers and participated in academic reviews during graduate school, which you can find [links to here](/publications/).
|
||||
|
||||
This website is also available on the gemini protocol as [gemini.bgenc.net](gemini://gemini.bgenc.net).
|
||||
Please see the ["Clients" section on this page](https://gemini.circumlunar.space/software/)
|
||||
to find a client, then connect to `gemini.bgenc.net`.
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
---
|
||||
title: Mass batch processing on the CLI
|
||||
date: 2022-03-19
|
||||
---
|
||||
|
||||
> This post is day 4 of me taking part in the
|
||||
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
|
||||
|
||||
Some time ago, I needed to process a lot of video files with vlc. This is
|
||||
usually pretty easy to do, `for file in *.mp4 ; do ffmpeg ... ; done` is about
|
||||
all you need in most cases. However, sometimes the files you are trying to
|
||||
process are in different folders. And sometimes you want to process some files
|
||||
in a folder but not others. That's the exact situation I was in, and I was
|
||||
wondering if I needed to find some graphical application with batch processing
|
||||
capabilities so I can queue up all the processing I need.
|
||||
|
||||
After a bit of thinking though, I realized I could do this very easily with a
|
||||
simple shell script! That shell script lives in my [mark-list](https://github.com/SeriousBug/mark-list)
|
||||
repository.
|
||||
|
||||
The idea is simple, you use the command to mark a bunch of files. Every file you
|
||||
mark is saved into a file for later use.
|
||||
|
||||
```bash
|
||||
$ mark-list my-video.mp4 # Choose a file
|
||||
Marked 1 file.
|
||||
$ mark-list *.webm # Choose many files
|
||||
Marked 3 files.
|
||||
$ cd Downloadsr
|
||||
$ mark-list last.mpg # You can go to other directories and keep marking
|
||||
```
|
||||
|
||||
You can mark a single file, or a bunch of files, or even navigate to other
|
||||
directories and mark files there.
|
||||
|
||||
Once you are done marking, you can recall what you marked with the same tool:
|
||||
|
||||
```bash
|
||||
$ mark-list --list
|
||||
/home/kaan/my-video.mp4
|
||||
/home/kaan/part-1.webm
|
||||
/home/kaan/part-2.webm
|
||||
/home/kaan/part-3.webm
|
||||
/home/kaan/Downloads/last.mpg
|
||||
```
|
||||
|
||||
You can then use this in the command line. For example, I was trying to convert everything to `mkv` files.
|
||||
|
||||
```bash
|
||||
for file in `mark-list --list` ; do ffmpeg -i "${file}" "${file}.mkv" ; done
|
||||
```
|
||||
|
||||
It works! After you are done with it, you then need to clear out your marks:
|
||||
|
||||
```
|
||||
mark-list --clear
|
||||
```
|
||||
|
||||
Hopefully this will be useful for someone else as well. It does make it a lot
|
||||
easier to just queue up a lot of videos, and convert all of them overnight.
|
|
@ -0,0 +1,44 @@
|
|||
---
|
||||
title: My response to Aurynn Shaw's "Contempt Culture" post
|
||||
date: 2022-03-27
|
||||
---
|
||||
|
||||
> This post is day 6 of me taking part in the
|
||||
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
|
||||
|
||||
I recently came across [Aurynn Shaw's article on "Contempt Culture"](https://blog.aurynn.com/2015/12/16-contempt-culture/).
|
||||
I'm a bit late to the party, but I wanted to talk about this too.
|
||||
|
||||
Aurynn's article talks about how some programming languages are considered
|
||||
inferior, and programmers using these languages are considered less competent.
|
||||
It's a good article, and you should take a look at it if you haven't.
|
||||
|
||||
## my thoughts
|
||||
|
||||
One thing I've come to realize over the years is that there are really no "bad
|
||||
programming languages". Ignoring esolangs like brainfuck which are not really
|
||||
meant to be used for anything serious, most programming languages are designed
|
||||
to fit a niche. I'm using the term like it's used in ecology: every programming
|
||||
language has a place in the ecosystem of technology and programming.
|
||||
|
||||
PHP is bad? PHP certainly has its drawbacks, but it also has its advantages.
|
||||
"Drop these files into a folder and it works" is an amazing way to get started
|
||||
programming. It's also a great way to inject a bit of dynamic content into
|
||||
otherwise static pages. In fact, it's simpler and more straightforward solution
|
||||
than building a REST API and a web app where you have to re-invent server side
|
||||
rendering just to get back to where PHP already was!
|
||||
|
||||
That's not to say PHP is perfect or the best language to use. It's a language I
|
||||
personally don't like. But that doesn't make it a bad or "stupid" programming
|
||||
language. At worst it's a programming language that doesn't fit my needs. If I
|
||||
extrapolate that and say that PHP is a bad language, that would instead show my
|
||||
ego. Do I really think I'm so great that anything I don't like is just
|
||||
immediately bad? Something Aurynn said resonates with me here:
|
||||
|
||||
> It didn't matter that it was (and remains) difficult to read, it was that we
|
||||
> were better for using it.
|
||||
|
||||
I just want to conclude this with one thing: next time you think a programming
|
||||
language or tool or whatever is bad, think to yourself whether that's because it
|
||||
doesn't feel cool or because you saw others making fun of it, or because you
|
||||
actually evaluated the pros and cons and came up with a calculated decision.
|
|
@ -0,0 +1,91 @@
|
|||
---
|
||||
title: Running graphical user services with systemd
|
||||
date: 2022-03-18
|
||||
---
|
||||
|
||||
> This post is day 3 of me taking part in the
|
||||
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
|
||||
|
||||
I've recently switched from KDE Plasma to sway as my window manager. I had a problem with the change though: the amazing kdeconnect service weren't working!
|
||||
|
||||
My first attempt at fixing this was to just add a lines into sway config to launch it along with sway.
|
||||
|
||||
```
|
||||
exec /usr/lib/kdeconnectd
|
||||
```
|
||||
|
||||
Looks simple enough. But for some reason, `kdeconnectd` would just disappear
|
||||
after a while. It would appear to run at startup, and then an hour or two later
|
||||
I pull up the kdeconnect app on my phone and it would tell me that my computer
|
||||
is disconnected.
|
||||
|
||||
The biggest issue here was that I had no way to see why kdeconnect had failed.
|
||||
In comes systemd to save the day. Systemd is a service manager, so it will
|
||||
actually maintain the logs for these services. That means if kdeconnect is
|
||||
crashing, I can check the logs for kdeconnect to see why it crashed. I can also
|
||||
configure it to auto-restart after a crash if I want to.
|
||||
|
||||
To launch graphical applications with systemd though, you need to pass the
|
||||
appropriate environment variables to it so it knows how to launch new windows.
|
||||
I added this line to my sway config to do exactly that.
|
||||
|
||||
```
|
||||
# Pass all variables to dbus & systemd to run graphical user services
|
||||
exec dbus-update-activation-environment --all --systemd
|
||||
```
|
||||
|
||||
Next, we need to write a service files to run the application. This is easier
|
||||
than it sounds, here's the service file I wrote for kdeconnect:
|
||||
|
||||
```
|
||||
[Unit]
|
||||
Description=Run kdeconnectd.
|
||||
After=graphical-session.target
|
||||
StartLimitIntervalSec=600
|
||||
StartLimitBurst=5
|
||||
|
||||
[Service]
|
||||
Type=basic
|
||||
ExecStart=/usr/lib/kdeconnectd
|
||||
Restart=on-failure
|
||||
RestartSec=5s
|
||||
|
||||
[Install]
|
||||
WantedBy=graphical-session.target
|
||||
```
|
||||
|
||||
I saved this as `~/.config/systemd/user/kdeconnectd.service`. Finally, enabled it for my user with `systemctl --user enable kdeconnectd.service` and then restarted.
|
||||
|
||||
The service is configured to automatically restart on failure, but not if it
|
||||
failed more than 5 times in the last 10 minutes. Systemd also waits 5 seconds
|
||||
before trying to restart the failed service. This way if it crashes for some
|
||||
reason, it will restart. But if it keeps crashing rapidly, it won't keep
|
||||
trying to restart which could take up too much system resources.
|
||||
|
||||
I can now check how the service is doing with systemd!
|
||||
|
||||
```
|
||||
Warning: The unit file, source configuration file or drop-ins of kdeconnectd.service changed on disk. Run 'systemctl --user daemon-reload>
|
||||
● kdeconnectd.service - Run kdeconnectd.
|
||||
Loaded: loaded (/home/kaan/.config/systemd/user/kdeconnectd.service; enabled; vendor preset: enabled)
|
||||
Active: active (running) since Thu 2022-03-17 14:18:15 EDT; 1h 46min ago
|
||||
Main PID: 2188363 (kdeconnectd)
|
||||
Tasks: 6 (limit: 77007)
|
||||
Memory: 24.2M
|
||||
CPU: 2.440s
|
||||
CGroup: /user.slice/user-1000.slice/user@1000.service/app.slice/kdeconnectd.service
|
||||
└─2188363 /usr/lib/kdeconnectd
|
||||
|
||||
Mar 17 14:20:58 eclipse systemd[817]: /home/kaan/.config/systemd/user/kdeconnectd.service:6: Unknown key name 'type' in section 'Service'>
|
||||
Mar 17 15:16:11 eclipse kdeconnectd[2188363]: QObject::connect(KWayland::Client::Registry, Unknown): invalid nullptr parameter
|
||||
Mar 17 15:16:11 eclipse kdeconnectd[2188363]: kdeconnect.plugin.battery: No Primary Battery detected on this system. This may be a bug.
|
||||
Mar 17 15:16:11 eclipse kdeconnectd[2188363]: kdeconnect.plugin.battery: Total quantity of batteries found: 0
|
||||
Mar 17 15:23:26 eclipse kdeconnectd[2188363]: QObject::connect(KWayland::Client::Registry, Unknown): invalid nullptr parameter
|
||||
Mar 17 15:23:26 eclipse kdeconnectd[2188363]: kdeconnect.plugin.battery: No Primary Battery detected on this system. This may be a bug.
|
||||
Mar 17 15:23:26 eclipse kdeconnectd[2188363]: kdeconnect.plugin.battery: Total quantity of batteries found: 0
|
||||
Mar 17 15:23:26 eclipse kdeconnectd[2188363]: QMetaObject::invokeMethod: No such method KIO::StoredTransferJob::slotDataReqFromDevice()
|
||||
Mar 17 15:24:35 eclipse kdeconnectd[2188363]: QMetaObject::invokeMethod: No such method KIO::StoredTransferJob::slotDataReqFromDevice()
|
||||
Mar 17 15:57:29 eclipse systemd[817]: /home/kaan/.config/systemd/user/kdeconnectd.service:9: Unknown key name 'type' in section 'Service'>
|
||||
```
|
||||
|
||||
A bunch of warnings so far, but no crashes yet. But if it does crash again, I'll finally know why.
|
|
@ -0,0 +1,47 @@
|
|||
---
|
||||
title: A little type system trick in Rust
|
||||
date: 2022-03-15
|
||||
---
|
||||
|
||||
> This post is day 1 of me taking part in the
|
||||
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
|
||||
|
||||
While working on a small project recently, I ended up writing this type in Rust.
|
||||
|
||||
```rust
|
||||
type ImageData = Arc<Mutex<Option<ImageBuffer<Rgba<u8>, Vec<u8>>>>>;
|
||||
```
|
||||
|
||||
Even though I wrote it myself, it actually took me a bit after writing it to
|
||||
figure out what this type was doing so I wanted to write about it.
|
||||
|
||||
Let me start from outside-in, the first type we have is `Arc`. `Arc` stands for
|
||||
"atomic reference counting". [Reference counting](https://en.wikipedia.org/wiki/Reference_counting)
|
||||
is a method to handle ownership of the data, or in other words to figure out
|
||||
when the data needs to be freed. Garbage collected languages do this
|
||||
transparently in the background, but in Rust we explicitly need to state that we
|
||||
want it. Atomic means this is done using [atomic operations](https://en.wikipedia.org/wiki/Linearizability#Primitive_atomic_instructions),
|
||||
so it is thread safe. In my case, I needed this because this data was going to
|
||||
be shared between multiple threads, and I didn't know exactly when I would be "done"
|
||||
with the data.
|
||||
|
||||
The next type is `Mutex`, which means [mutual exclusion](https://en.wikipedia.org/wiki/Lock_(computer_science))
|
||||
or locking. Locks are used to restrict access to data to a single thread at a time.
|
||||
That means whatever type is inside of this is not thread safe,
|
||||
so I'm using the lock to protect it. Which is true!
|
||||
|
||||
The type after that is `Option`. This basically means "nullable", there may or may not be a thing inside this.
|
||||
The interesting thing here is that this is a [sum type](https://en.wikipedia.org/wiki/Tagged_union),
|
||||
so Rust helps remind us that this is nullable without introducing a nullability concept to the language. It's just part of the type system!
|
||||
|
||||
Then we have `ImageBuffer`, a type from the popular [image crate](https://docs.rs/image/latest/image/index.html).
|
||||
Not much to talk about with this, that's the data I wanted to store.
|
||||
|
||||
The next thing that *is* interesting is the `Rgba<u8>` and `Vec<u8>` inside the image buffer.
|
||||
What that means (and I'm speculating here because I'm lazy/too busy to check), is that
|
||||
`Rgba` is just a basic wrapper type (or a "newtype"). It makes the compiler enforce the type of the
|
||||
image data that's stored in this image buffer, so the user doesn't mix up different data types.
|
||||
Similar for `Vec<u8>`, (I think) it means that the data inside this buffer is stored in a vector.
|
||||
|
||||
Finally, `u8` is probably self descriptive, the pixels and the vector are made out of 8-bit unsigned integers.
|
||||
|
|
@ -0,0 +1,83 @@
|
|||
---
|
||||
title: State of Rust GUIs
|
||||
date: 2022-03-17
|
||||
---
|
||||
|
||||
> This post is day 2 of me taking part in the
|
||||
> [#100DaysToOffload](https://100daystooffload.com/) challenge.
|
||||
|
||||
The website [Are we GUI Yet?](https://www.areweguiyet.com/) helpfully lists a
|
||||
lot of the libraries and frameworks available for making a GUI in Rust. I've
|
||||
been looking into making a GUI program in Rust, so I've been working my way
|
||||
through some of these options.
|
||||
|
||||
This is not a through review, just my thoughts after a brief look. I'd recommend
|
||||
looking over the website and deciding for yourself.
|
||||
|
||||
## Best candidate: Dioxus
|
||||
- Website: https://dioxuslabs.com/
|
||||
|
||||
Dioxus is probably the option I like the best from a quick look. Declarative
|
||||
applications similar to React, encapsulated components, first class async
|
||||
support, and good type checking.
|
||||
|
||||
Downsides? Right now it's web only. Desktop applications are just web
|
||||
applications rendered inside a web view. That's okay for cross platform apps,
|
||||
but not for what I want to do which is a lightweight native application.
|
||||
|
||||
## Better Electron: Tauri
|
||||
- Website: https://github.com/tauri-apps/tauri
|
||||
|
||||
Tauri is a really good replacement for Electron. You can see the comparison on
|
||||
their Github page, smaller binaries, less memory use, and faster launch times.
|
||||
|
||||
But again, it is a web app running in a web view. Not a native desktop app. Even
|
||||
though Tauri uses less memory than electron, it still uses ~180 MB according to
|
||||
their comparison. And the fast launch time is still around 0.4 seconds, way
|
||||
longer than what I would expect.
|
||||
|
||||
## My current preference: Slint
|
||||
- Website: https://slint-ui.com/
|
||||
|
||||
I really like Slint. It is a native GUI with their own OpenGL renderer, and an
|
||||
optional Qt backend. From some basic experimentation, it seems to launch in less
|
||||
than 50ms, and uses less than 80 MB of memory (mostly shared libraries).
|
||||
|
||||
You can write the code in either `.slint` files (and they actually have okay
|
||||
editor support for this file type), or inside macros in your code files. The
|
||||
code also looks pretty intuitive.
|
||||
|
||||
The downsides? The theming support is not great/nonexistent, you can't
|
||||
dynamically generate UI elements (well kinda, you can generate them based on
|
||||
properties you change at runtime, but the components themselves are hardcoded),
|
||||
and the code sometimes gets awkward due to current limitations.
|
||||
|
||||
```rust
|
||||
MainWindow := Window {
|
||||
// You then have to bind to this callback inside rust code. No way to just write a hook that calls a rust function.
|
||||
callback save_to_file(string);
|
||||
|
||||
HorizontalLayout {
|
||||
height: 32px;
|
||||
|
||||
FilePath := LineEdit {
|
||||
placeholder_text: "placeholder here";
|
||||
}
|
||||
Button {
|
||||
text: "Save to file";
|
||||
clicked => { save_to_file(FilePath.text); }
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
There is also no way to do some things, like setting a dialog hint for your main
|
||||
window, which is something I needed to do.
|
||||
|
||||
## Conclusion?
|
||||
|
||||
It looks like the state of GUIs in rust is still "not yet". There are a few more
|
||||
projects I need to look at, like [Relm](https://github.com/antoyo/relm), but
|
||||
their code looks way too verbose to me. In the end, I think the best option
|
||||
might be to just write my GUI in C++ with Qt, and maybe integrate bits written
|
||||
in rust inside of that.
|
|
@ -0,0 +1,36 @@
|
|||
# Homepage of Kaan Barmore-Genç
|
||||
|
||||
Hey folks!
|
||||
|
||||
I'm a Software Engineer at Dendron, and a recent Master's graduate from the Ohio
|
||||
State University. I'm an avid Linux user, an enthusiast of many programming
|
||||
languages, a home cook, and an amateur gardener.
|
||||
|
||||
=> https://dendron.so Dendron
|
||||
=> https://bgenc.net/recipes/ My recipes
|
||||
|
||||
My interests include building web and mobile applications, both at the front and
|
||||
back end. Over the years I learned and used many programming languages and
|
||||
technologies, including JavaScript, TypeScript, React, React Native, Rust,
|
||||
Python, Java, C, C++, Clojure, and Haskell. Pretty much everthing I've worked on
|
||||
is open source and available on my Github page.
|
||||
|
||||
I published several papers and participated in academic reviews during graduate school. You can find them below.
|
||||
|
||||
=> /publications.gmi My publications
|
||||
|
||||
Here are some links if you need to reach me.
|
||||
|
||||
=> mailto:kaan@bgenc.net kaan@bgenc.net
|
||||
=> /extra/kaangenc.gpg GPG key
|
||||
=> https://github.com/SeriousBug Github
|
||||
=> https://www.linkedin.com/in/kaan-genc-8489b9205/ LinkedIn
|
||||
=> /extra/cv.pdf My CV
|
||||
=> https://mastodon.technology/@kaan My Mastodon
|
||||
|
||||
This page is also available on HTTP/HTML if you prefer that.
|
||||
|
||||
=> https://bgenc.net HTTP mirror
|
||||
|
||||
Finally, below is a list of all my blog posts. These are not sorted by date at the moment, but I'm working on fixing that soon.
|
||||
|
|
@ -21,7 +21,7 @@
|
|||
(when (not= slug "index") [:a.home {:href "/"} "Home"])
|
||||
[:img.picture {:alt "A photo of Kaan, after his OOPSLA 2019 talk." :src "/img/profile.jpg"}]
|
||||
[:div.name "Kaan Barmore-Genç"]
|
||||
[:div.title "M.S. Software Engineer"]
|
||||
[:div.title "M.S."]
|
||||
[:div.spacer]
|
||||
[:div.title "Software Engineer"]
|
||||
[:div.affiliation [:a {:href "http://dendron.so/"} "Dendron"]]
|
||||
|
|
Loading…
Reference in New Issue