diff --git a/internal/webserver/server_test.go b/internal/webserver/server_test.go index 9551ac7..ec573b3 100644 --- a/internal/webserver/server_test.go +++ b/internal/webserver/server_test.go @@ -95,7 +95,7 @@ func TestUserFeedWithEntityInBio(t *testing.T) { root, err := html.Parse(resp.Body) require.NoError(err) - bio_entities := cascadia.QueryAll(root, selector(".user-bio .entity")) + bio_entities := cascadia.QueryAll(root, selector(".user-header__bio .entity")) require.Len(bio_entities, 1) assert.Equal(bio_entities[0].FirstChild.Data, "@SheathUnderwear") } @@ -192,7 +192,7 @@ func TestUserFollowers(t *testing.T) { root, err := html.Parse(resp.Body) require.NoError(err) - assert.Len(cascadia.QueryAll(root, selector(".users-list-container > .user")), 2) + assert.Len(cascadia.QueryAll(root, selector(".users-list > .user")), 2) } func TestUserFollowees(t *testing.T) { @@ -204,7 +204,7 @@ func TestUserFollowees(t *testing.T) { root, err := html.Parse(resp.Body) require.NoError(err) - assert.Len(cascadia.QueryAll(root, selector(".users-list-container > .user")), 1) + assert.Len(cascadia.QueryAll(root, selector(".users-list > .user")), 1) } // Timeline page @@ -363,7 +363,7 @@ func TestSearchUsers(t *testing.T) { require.Equal(resp.StatusCode, 200) root, err := html.Parse(resp.Body) require.NoError(err) - user_elements := cascadia.QueryAll(root, selector(".users-list-container .user")) + user_elements := cascadia.QueryAll(root, selector(".users-list .user")) assert.Len(user_elements, 2) assert.Contains(cascadia.Query(root, selector("#search-bar")).Attr, html.Attribute{Key: "value", Val: "no"}) } @@ -456,7 +456,7 @@ func TestTweetsWithContent(t *testing.T) { root, err := html.Parse(resp.Body) require.NoError(err) assert.Len(cascadia.QueryAll(root, selector(".poll")), 1) - assert.Len(cascadia.QueryAll(root, selector(".poll-choice")), 4) + assert.Len(cascadia.QueryAll(root, selector(".poll__choice")), 4) // Video resp = do_request(httptest.NewRequest("GET", "/tweet/1453461248142495744", nil)) @@ -478,7 +478,7 @@ func TestTweetsWithContent(t *testing.T) { root, err = html.Parse(resp.Body) require.NoError(err) assert.Len(cascadia.QueryAll(root, selector(".space")), 1) - assert.Len(cascadia.QueryAll(root, selector("ul.space-participants-list li")), 9) + assert.Len(cascadia.QueryAll(root, selector("ul.space__participants-list li")), 9) } func TestTweetWithEntities(t *testing.T) { @@ -621,7 +621,7 @@ func TestListsIndex(t *testing.T) { require.NoError(err) // Check that there's at least 2 Lists - assert.True(t, len(cascadia.QueryAll(root, selector(".users-list-preview"))) >= 2) + assert.True(t, len(cascadia.QueryAll(root, selector(".list-preview"))) >= 2) } func TestListDetail(t *testing.T) { @@ -633,7 +633,7 @@ func TestListDetail(t *testing.T) { require.Equal(resp.StatusCode, 200) root, err := html.Parse(resp.Body) require.NoError(err) - assert.Len(cascadia.QueryAll(root, selector(".users-list-container .author-info")), 5) + assert.Len(cascadia.QueryAll(root, selector(".users-list .author-info")), 5) // Feed resp1 := do_request(httptest.NewRequest("GET", "/lists/2", nil)) @@ -662,7 +662,7 @@ func TestListAddAndDeleteUser(t *testing.T) { require.Equal(resp.StatusCode, 200) root, err := html.Parse(resp.Body) require.NoError(err) - assert.Len(cascadia.QueryAll(root, selector(".users-list-container .author-info")), 2) + assert.Len(cascadia.QueryAll(root, selector(".users-list .author-info")), 2) // Add a user resp_add := do_request(httptest.NewRequest("GET", "/lists/2/add_user?user_handle=cernovich", nil)) @@ -674,7 +674,7 @@ func TestListAddAndDeleteUser(t *testing.T) { require.Equal(resp.StatusCode, 200) root, err = html.Parse(resp.Body) require.NoError(err) - assert.Len(cascadia.QueryAll(root, selector(".users-list-container .author-info")), 3) + assert.Len(cascadia.QueryAll(root, selector(".users-list .author-info")), 3) // Delete a user resp_remove := do_request(httptest.NewRequest("GET", "/lists/2/remove_user?user_handle=cernovich", nil)) @@ -686,7 +686,7 @@ func TestListAddAndDeleteUser(t *testing.T) { require.Equal(resp.StatusCode, 200) root, err = html.Parse(resp.Body) require.NoError(err) - assert.Len(cascadia.QueryAll(root, selector(".users-list-container .author-info")), 2) + assert.Len(cascadia.QueryAll(root, selector(".users-list .author-info")), 2) } func TestCreateNewList(t *testing.T) { @@ -698,7 +698,7 @@ func TestCreateNewList(t *testing.T) { require.Equal(resp.StatusCode, 200) root, err := html.Parse(resp.Body) require.NoError(err) - num_lists := len(cascadia.QueryAll(root, selector(".users-list-preview"))) + num_lists := len(cascadia.QueryAll(root, selector(".list-preview"))) // Create a new list resp_add := do_request(httptest.NewRequest("POST", "/lists", strings.NewReader(`{"name": "My New List"}`))) @@ -710,7 +710,7 @@ func TestCreateNewList(t *testing.T) { require.Equal(resp.StatusCode, 200) root, err = html.Parse(resp.Body) require.NoError(err) - assert.Len(cascadia.QueryAll(root, selector(".users-list-preview")), num_lists+1) + assert.Len(cascadia.QueryAll(root, selector(".list-preview")), num_lists+1) } // Messages @@ -732,8 +732,8 @@ func TestMessagesIndexPage(t *testing.T) { resp := recorder.Result() root, err := html.Parse(resp.Body) require.NoError(err) - assert.Len(cascadia.QueryAll(root, selector(".chat-list .chat")), 2) - assert.Len(cascadia.QueryAll(root, selector(".chat-view .dm-message-and-reacts-container")), 0) // No messages until you click on one + assert.Len(cascadia.QueryAll(root, selector(".chat-list .chat-list-entry")), 2) + assert.Len(cascadia.QueryAll(root, selector(".chat-view .dm-message")), 0) // No messages until you click on one } // Open a chat room @@ -752,8 +752,8 @@ func TestMessagesRoom(t *testing.T) { resp := recorder.Result() root, err := html.Parse(resp.Body) require.NoError(err) - assert.Len(cascadia.QueryAll(root, selector(".chat-list .chat")), 2) // Chat list still renders - assert.Len(cascadia.QueryAll(root, selector("#chat-view .dm-message-and-reacts-container")), 5) + assert.Len(cascadia.QueryAll(root, selector(".chat-list .chat-list-entry")), 2) // Chat list still renders + assert.Len(cascadia.QueryAll(root, selector("#chat-view .dm-message")), 5) // Should have the poller at the bottom node := cascadia.Query(root, selector("#new-messages-poller")) @@ -782,7 +782,7 @@ func TestMessagesRoomPollForUpdates(t *testing.T) { resp := recorder.Result() root, err := html.Parse(resp.Body) require.NoError(err) - assert.Len(cascadia.QueryAll(root, selector(".dm-message-and-reacts-container")), 3) + assert.Len(cascadia.QueryAll(root, selector(".dm-message")), 3) // Should have the poller at the bottom node := cascadia.Query(root, selector("#new-messages-poller")) @@ -811,7 +811,7 @@ func TestMessagesRoomPollForUpdatesEmptyResult(t *testing.T) { resp := recorder.Result() root, err := html.Parse(resp.Body) require.NoError(err) - assert.Len(cascadia.QueryAll(root, selector(".dm-message-and-reacts-container")), 0) + assert.Len(cascadia.QueryAll(root, selector(".dm-message")), 0) // Should have the poller at the bottom, with the same value as previously node := cascadia.Query(root, selector("#new-messages-poller")) diff --git a/internal/webserver/static/styles.css b/internal/webserver/static/styles.css index 7206e36..5350953 100644 --- a/internal/webserver/static/styles.css +++ b/internal/webserver/static/styles.css @@ -1,19 +1,19 @@ :root { - --color-twitter-text-gray: #536171; - --color-twitter-blue: #1b95e0; /* hsl(203, 78%, 49%) */ - --color-twitter-blue-light: #7cc5f6; /* hsl(204, 87%, 73%) */ - --color-twitter-blue-extra-light: hsl(204, 95%, 85%); - --color-twitter-off-white: #f7f9f9; /* hsl(180, 14%, 97%) */ - --color-twitter-off-white-dark: #dae5e5; /* hsl(180, 17%, 88%) */ - --color-outline-gray: #dcdcdc; - --color-twitter-text-gray: #536471; + --color-twitter-text-gray: #536171; + --color-twitter-blue: #1b95e0; /* hsl(203, 78%, 49%) */ + --color-twitter-blue-light: #7cc5f6; /* hsl(204, 87%, 73%) */ + --color-twitter-blue-extra-light: hsl(204, 95%, 85%); + --color-twitter-off-white: #f7f9f9; /* hsl(180, 14%, 97%) */ + --color-twitter-off-white-dark: #dae5e5; /* hsl(180, 17%, 88%) */ + --color-outline-gray: #dcdcdc; + --color-twitter-text-gray: #536471; - --color-twitter-danger-red: #f4212e; /* hsl(356, 91%, 54%) */ - --color-twitter-danger-red2: #de1b28; /* hsl(356, 78%, 49%) */ - --color-twitter-danger-red2-light: #f67e86; /* hsl(356, 87%, 73%) */ - --color-twitter-danger-red2-hover: #f2a6aa; /* hsl(357, 75%, 80%);*/ - --color-space-purple: #a49bfd; - --color-space-purple-outline: #6452fc; + --color-twitter-danger-red: #f4212e; /* hsl(356, 91%, 54%) */ + --color-twitter-danger-red2: #de1b28; /* hsl(356, 78%, 49%) */ + --color-twitter-danger-red2-light: #f67e86; /* hsl(356, 87%, 73%) */ + --color-twitter-danger-red2-hover: #f2a6aa; /* hsl(357, 75%, 80%);*/ + --color-space-purple: #a49bfd; + --color-space-purple-outline: #6452fc; /* const QColor COLOR_OUTLINE_GRAY = QColor(220, 220, 220); const QColor COLOR_TWITTER_BLUE = QColor(27, 149, 224); @@ -24,7 +24,7 @@ const QColor COLOR_TWITTER_TEXT_GRAY = QColor(83, 100, 113); const QColor COLOR_BACKGROUND_GREEN = QColor(40, 205, 50); -const QColor COLOR_RED = QColor(255, 0, 0); +const QColor COLOR_RED = QColor(255, 0, 0); const QColor COLOR_SPACE_PURPLE = QColor(164, 155, 253); const QColor COLOR_SPACE_PURPLE_OUTLINE = QColor(100, 82, 252); @@ -43,48 +43,56 @@ const QColor COLOR_SPACE_PURPLE_OUTLINE = QColor(100, 82, 252); ***************************************************************************************************/ html { - /* - * Force scrollbar, even when it fits on 1 page. Prevents viewport from resizing -> flickering - * and stuff moving between page loads - */ - overflow-y: scroll; + /* + * Force scrollbar, even when it fits on 1 page. Prevents viewport from resizing -> flickering + * and stuff moving between page loads + */ + overflow-y: scroll; } body { - margin: 0 30%; - min-height: 100vh; + /* So that toasts can be positioned relative to `body` (rather than `html`). + * This is useful because it wil then use the `body`'s width (i.e., accounting for the big fat margins). + */ + position: relative; - border-color: var(--color-twitter-off-white-dark); - border-right-style: solid; - border-left-style: solid; - border-width: 1px; + margin: 0 30%; + min-height: 100vh; - font-family: "Titillium Web"; + border-color: var(--color-twitter-off-white-dark); + border-right-style: solid; + border-left-style: solid; + border-width: 1px; + + font-family: "Titillium Web"; } input, select { - font-family: inherit; - font-size: 1em; - padding: 0.2em 0.6em; - box-sizing: border-box; - border-radius: 0.5em; + font-family: inherit; + font-size: 1em; + padding: 0.2em 0.6em; + box-sizing: border-box; + border-radius: 0.5em; } input[type="submit"] { - background-color: var(--color-twitter-blue-light); - width: 10em; - padding: 1em; - border-radius: 1em; - font-size: 1em; - cursor: pointer; + background-color: var(--color-twitter-blue-light); + width: 10em; + border-radius: 1em; + font-size: 1em; + cursor: pointer; } a { - text-decoration: none; - color: inherit; + text-decoration: none; + color: inherit; + cursor: pointer; +} +ul { + list-style: none; } h1 { - margin: 0.5em 0; - text-align: center; + margin: 0.5em 0; + text-align: center; } h3 { - margin: 0.5em 0; + margin: 0.5em 0; } @@ -99,37 +107,92 @@ h3 { ***************************************************************************************************/ .row { - display: flex; - flex-direction: row; - align-items: center; + display: flex; + flex-direction: row; + align-items: center; } .row--spread { - justify-content: space-between; + justify-content: space-between; } /* A list of items separated by interpuncts */ .inline-dotted-list { - list-style: none; - margin: 0; -} -.inline-dotted-list > * { - display: inline; -} -.inline-dotted-list > *:after { - content: " ⋅"; -} -.inline-dotted-list > *:last-child:after { - content: ""; + margin: 0; + + & > * { + display: inline; + } + & > *:after { + content: " ⋅"; + } + & > *:last-child:after { + content: ""; + } } .rounded-gray-outline { - outline-color: lightgray; - outline-style: solid; - outline-width: 1px; - overflow: hidden; - border-radius: 1.5em; + outline-color: lightgray; + outline-style: solid; + outline-width: 1px; + overflow: hidden; + border-radius: 1.5em; } +.circle-outline { + display: flex; + border-radius: 50%; + outline: 1px solid #777; + margin: 0 0.4em; + font-size: 0.8em; + padding: 0.2em; + box-sizing: border-box; +} + +.button { + display: flex; /* Prevent from having extra space at the bottom, looking weird*/ + padding: 0.5em; + margin: 0.2em; + border-radius: 100em; /* any large amount, just don't use % because then it makes an ellipse */ + cursor: pointer; + + &:hover { + background-color: var(--color-twitter-blue-light); + } + &:active { + transform: translate(0.1em, 0.1em); + background-color: var(--color-twitter-blue); + } + + &.button--danger { + background-color: var(--color-twitter-danger-red2); + + &:hover { + background-color: var(--color-twitter-danger-red2-light); + } + &:active { + background-color: var(--color-twitter-danger-red2); + } + } +} + +.labelled-icon { + display: flex; + flex-direction: row; + align-items: center; + + & label { + padding: 0 0.3em; + white-space: nowrap; + cursor: unset; /*