somewhere to talk about random ideas and projects like everyone else

stuff

Why my Streamie fork is better than everyone else’s 01 September 2010

So the future is here and everyone is forking running websites. The rate of development is pretty insane and I’ve already disabled Chromed Bird and I’m switching to having Streamie as a pinned tab, which also leads inevitably to the question “Why is a pinned application tab aesthetically different from a Browser Action?” . But back to the point, this post will detail every little feature that is utterly insignificant in the grand scheme of things that I felt like improving on in the streamie client.

Retweeters show a little icon

This is a feature that was in Chromed Bird and Tweetie and was pretty easy so why not implement it.

Short links are automatically expanded

This feature is accomplished using Dion Almaer’s endpoint resolver.

Better link detection

My fork uses John Gruber’s improved liberal, accurate Regex pattern for matching URLs. This allows cases like the above to be properly ended at the parenthesis while still allowing wikipedia links that include parentheses.

What client was used to post it.

Mine displays what client the poster is using.

You can try it out on http://antimatter15.streamie.org/ But seriously, all the forking of streamie is probably great for the project, and my role is very insignificant, and it would be great if some of the features got into the master branch :)



HTTP based federated protocol for real time hierarchical message manipulation 29 August 2010

In other words. It’s like google wave, but simpler in every possible way.

This protocol uses two servers. The federation server and the storage server. The latter is incredably simple. In fact, the reference implementation is only about 200 lines of JS (Node.JS FTW). Thats because a storage server accomplishes just about three things. It receives message deltas. It applies them. And it pushes the delta to all subscribers. The subscribers are the federation servers, they act on the behalf of multiple clients, keeping track of users, their inboxes, etc.

Anyway, the big part about the design is that there is only one unit of information, and that is the message. There’s no such thing as waves, wavelets, conversations, private replies, threads (sort of lying here), blips and other information. It’s just messages. Messages are stored on storage servers, and are filled with HTML and a tree of information.

Messages can have other messages inside them. It’s just some xml-ish stuff. <thread></thread> is a thread and <message name=”http://blahblahblah.com/blahblahblah"></message&gt; is a message that goes inside the thread. You can stick it anywhere. In the middle (inline replies!) or at the end (normal replies!).

Messages don’t even have to have text. Gadgets are just messages that are slightly different.

http://github.com/antimatter15/awesomeness

There’s a lot that it doesn’t do because I’m too lazy to do it. And I can’t give you a live demo because I don’t have a node-enabled server.


HTML5/CSS3 Zooming User Interface 29 August 2010

I’m taking liberties with the concept of zooming user interfaces, but this is an example of something that lets you browse wikipedia by zooming in toward a link, and zooming out to go back. So I guess it’s more of a z-axis spatial visualization for history somewhat similar to what I guess Apple’s Time Machine program is like (though I have never tried it).

It uses html5’s popState and pushState to get the URL to change without reloading the page (which, btw people should use instead of the weird /#/ urls). It uses webkit transformations, which probably aren’t part of CSS3 since it’s vendor specific, but I haven’t had time to hack it to work on firefox, feel free to fork.

javascript:(function(){var scale=1,tx=innerWidth/2,ty=innerHeight/2,sx=innerWidth/2,sy=innerHeight/2;document.onmousewheel=function(a){if(a.wheelDelta){if(a.wheelDelta>0)scale*=a.wheelDelta/1000;if(a.wheelDelta<0)scale/=-a.wheelDelta/1000}scale<0.05&&history.go(-1);showTransform();a.preventDefault()};window.onpopstate=function(a){loadPage(a.state.url)}; function showTransform(){document.body.style.webkitTransform="scale("+scale+") translate("+(innerWidth/2-tx)+"px,"+(innerHeight/2-ty)+"px)";var a=document.elementFromPoint(innerWidth/2,innerHeight/2);if(a.nodeName=="A"&&a.offsetWidth*scale>0.3*innerWidth&&a.offsetHeight*scale>0.3*innerHeight){console.log("clicky");loadPage(a.href);history.pushState({url:a.href},a.href,a.href)}} function loadPage(a){var b=new XMLHttpRequest;b.open("get",a,true);b.onload=function(){document.body.innerHTML=b.responseText;showTransform()};b.send(null);scale=1;tx=innerWidth/2;ty=innerHeight/2;sx=innerWidth/2;sy=innerHeight/2;showTransform()}var dragging=false;document.onmousemove=function(a){if(dragging){tx+=(sx-a.pageX)/scale;ty+=(sy-a.pageY)/scale;sx=a.pageX;sy=a.pageY;showTransform();a.preventDefault();a.stopPropagation()}}; document.onmousedown=function(a){dragging=true;sx=a.pageX;sy=a.pageY;a.preventDefault()};document.onclick=function(a){a.preventDefault()};document.onmouseup=function(a){dragging=false;a.preventDefault()};})()

So that’s a bookmarklet. feel free to click it on this site and it’ll get rid of the infinite scrolling and for some reason it doesn’t work well on this site. Try it on wikipedia.

(function(){
    var scale=1,
        tx=innerWidth/2,
        ty=innerHeight/2,
        sx=innerWidth/2,
        sy=innerHeight/2,
        mx=innerWidth/2,
        my=innerHeight/2,

    document.onmousewheel=function(a){
        console.log(a.wheelDelta, scale)
        scale = Math.exp(Math.log(scale) + a.wheelDelta / 200)
        if(scale<0.05) history.go(-1);
        showTransform();
        a.preventDefault()
    };
    window.onpopstate=function(a){
        loadPage(a.state.url)
    };
    function showTransform(){
        document.body.style.webkitTransform="scale("+scale+") translate("+(mx-tx)+"px,"+(my-ty)+"px)";
        var a=document.elementFromPoint(innerWidth/2,innerHeight/2);
        if(a.nodeName=="A"&&a.offsetWidth*scale>0.3*innerWidth&&a.offsetHeight*scale>0.3*innerHeight){
            console.log("clicky");
            loadPage(a.href);
            history.pushState({url:a.href},a.href,a.href)
        }
    } 
    function loadPage(a){
        var b=new XMLHttpRequest;
        b.open("get",a,true);
        b.onload=function(){
            document.body.innerHTML=b.responseText;
            showTransform()
        };
        b.send(null);
        scale=1;
        tx=innerWidth/2;
        ty=innerHeight/2;
        sx=innerWidth/2;
        sy=innerHeight/2;
        showTransform()
    }
    var dragging=false;
    document.onmousemove=function(a){

        if(dragging){
            tx+=(sx-a.pageX)/scale;
            ty+=(sy-a.pageY)/scale;
            sx=a.pageX;
            sy=a.pageY;
            showTransform();
            a.preventDefault();
            a.stopPropagation()
        }
    }; 
    document.onmousedown=function(a){
        dragging=true;
        sx=a.pageX;
        sy=a.pageY;
        a.preventDefault()
    };
    document.onclick=function(a){
        a.preventDefault()
    };
    document.onmouseup=function(a){
        dragging=false;
        a.preventDefault()
    };
})()