├── .gitignore
├── .github
└── preview.png
├── assets
├── icons
│ ├── 16x16.png
│ ├── 48x48.png
│ ├── 64x64.png
│ ├── 96x96.png
│ └── 128x128.png
├── tabnews.svg
├── dailydev.svg
├── javascript.svg
├── favicon.svg
├── logo.svg
└── scroll.svg
├── js
├── config.js
├── weather.js
└── main.js
├── manifest.json
├── README.md
├── styles
└── style.css
└── index.html
/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_STORE
--------------------------------------------------------------------------------
/.github/preview.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birobirobiro/DevNews/HEAD/.github/preview.png
--------------------------------------------------------------------------------
/assets/icons/16x16.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birobirobiro/DevNews/HEAD/assets/icons/16x16.png
--------------------------------------------------------------------------------
/assets/icons/48x48.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birobirobiro/DevNews/HEAD/assets/icons/48x48.png
--------------------------------------------------------------------------------
/assets/icons/64x64.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birobirobiro/DevNews/HEAD/assets/icons/64x64.png
--------------------------------------------------------------------------------
/assets/icons/96x96.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birobirobiro/DevNews/HEAD/assets/icons/96x96.png
--------------------------------------------------------------------------------
/assets/icons/128x128.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/birobirobiro/DevNews/HEAD/assets/icons/128x128.png
--------------------------------------------------------------------------------
/js/config.js:
--------------------------------------------------------------------------------
1 | // Substitua a string abaixo com a sua chave de API do OpenWeatherMap, que você pode obter em https://openweathermap.org/api
2 | export const API_KEY = "b94fc3e6b8b15def8097fd39f888d555";
3 |
--------------------------------------------------------------------------------
/manifest.json:
--------------------------------------------------------------------------------
1 | {
2 | "manifest_version": 3,
3 | "name": "DevNews",
4 | "version": "1.0",
5 | "description": "Suas notícias de programação em um só lugar",
6 | "icons": {
7 | "16": "/assets/icons/16x16.png",
8 | "48": "/assets/icons/48x48.png",
9 | "64": "/assets/icons/64x64.png",
10 | "96": "/assets/icons/96x96.png",
11 | "128": "/assets/icons/128x128.png"
12 | },
13 | "chrome_url_overrides": {
14 | "newtab": "index.html"
15 | },
16 | "permissions": ["geolocation"]
17 | }
18 |
--------------------------------------------------------------------------------
/assets/tabnews.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/assets/dailydev.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | DevNews
2 |
3 |
4 |
5 |
6 |
7 | ## 🚀 Tecnologias
8 |
9 | Esse projeto foi desenvolvido com as seguintes tecnologias:
10 |
11 | - HTML
12 | - CSS
13 | - JavaScript
14 |
15 | ## 🌍 Acesse o site:
16 |
17 | - [https://devnews.birobirobiro.dev](https://devnews.birobirobiro.dev)
18 |
19 | ## 🚧 Instalação da extensão:
20 |
21 | - Baixe o [.zip](https://github.com/birobirobiro/dev-news/archive/refs/heads/master.zip)
22 | - Extraia em uma pasta em seu computador
23 | - No Google Chrome acesse a página [chrome://extensions/](chrome://extensions/)
24 | - Ative o modo de desenvolvedor
25 | - Clique em Load Unpacked
26 | - Escolha a pasta extraída e pronto
27 |
28 | ---
29 |
30 | Feito com ♥ by [birobirobiro](https://birobirobiro.dev)
31 |
--------------------------------------------------------------------------------
/assets/javascript.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/assets/favicon.svg:
--------------------------------------------------------------------------------
1 |
5 |
--------------------------------------------------------------------------------
/assets/logo.svg:
--------------------------------------------------------------------------------
1 |
4 |
--------------------------------------------------------------------------------
/js/weather.js:
--------------------------------------------------------------------------------
1 | import { API_KEY } from "./config.js";
2 |
3 | const greeting = document.getElementById("greeting");
4 | const data = document.getElementById("data");
5 | const hora = document.getElementById("hora");
6 | const previsaoTempo = document.getElementById("previsao-tempo");
7 |
8 | const now = new Date();
9 | const dateNow = now.getHours();
10 |
11 | window.onload = function () {
12 | // Define a saudação com base na hora atual
13 | if (dateNow >= 5 && dateNow < 12) {
14 | greeting.textContent = "Bom dia! Hoje é";
15 | } else if (dateNow >= 12 && dateNow < 18) {
16 | greeting.textContent = "Boa tarde! Hoje é";
17 | } else {
18 | greeting.textContent = "Boa noite! Hoje é";
19 | }
20 |
21 | // Exibe a data e hora atual
22 | data.textContent = now.toLocaleDateString("pt-BR", {
23 | weekday: "long",
24 | });
25 |
26 | hora.textContent = now.toLocaleTimeString("pt-BR", {
27 | hour: "2-digit",
28 | minute: "2-digit",
29 | });
30 |
31 | previsaoTempo.textContent = "Carregando previsão do tempo...";
32 |
33 | if ("geolocation" in navigator) {
34 | navigator.geolocation.getCurrentPosition(
35 | (position) => {
36 |
37 | // Para usar a localização do navegador, descomente esse código
38 | const latitude = position.coords.latitude;
39 | const longitude = position.coords.longitude;
40 |
41 | // Latitude e longitude de São Paulo
42 | // const latitude = -23.5489;
43 | // const longitude = -46.6388;
44 |
45 | fetch(
46 | `https://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}&lang=pt_br&units=metric`
47 | )
48 | .then((response) => response.json())
49 | .then((data) => {
50 | const description = data.weather[0].description;
51 | const descriptionCapitalized =
52 | description.charAt(0).toUpperCase() + description.slice(1);
53 | const temp = data.main.temp;
54 | const tempFormatted = temp.toFixed(0);
55 | const city = data.name;
56 | const weatherIconCode = data.weather[0].icon;
57 | const weatherIconUrl = `https://openweathermap.org/img/wn/${weatherIconCode}.png`;
58 |
59 | previsaoTempo.innerHTML = `
60 |
61 |

${descriptionCapitalized} e temperatura de ${tempFormatted}°C em ${city}
62 |
`;
63 | })
64 |
65 | .catch((error) => {
66 | console.error(error);
67 | previsaoTempo.textContent =
68 | "Não foi possível obter a previsão do tempo";
69 | });
70 | },
71 |
72 | (error) => {
73 | console.error(error);
74 | previsaoTempo.textContent = "Não foi possível obter a localização";
75 | }
76 | );
77 | } else {
78 | previsaoTempo.textContent = "Geolocalização não suportada pelo navegador";
79 | }
80 | };
81 |
--------------------------------------------------------------------------------
/js/main.js:
--------------------------------------------------------------------------------
1 | function GithubTrending() {
2 | fetch("https://api.hackertab.dev/data/v2/github/global/daily.json")
3 | .then((response) => response.json())
4 | .then((data) => {
5 | const githubSection = document.querySelector("#github .scroll");
6 | const content = data
7 | .map(
8 | (item) => `
9 |
14 | `
15 | )
16 | .join("");
17 | githubSection.innerHTML = content;
18 | })
19 | .catch((error) => console.error(error));
20 | }
21 |
22 | function ProductHunt() {
23 | fetch("https://api.hackertab.dev/data/v2/producthunt.json")
24 | .then((response) => response.json())
25 | .then((data) => {
26 | const producthuntSection = document.querySelector(
27 | "#product-hunt .scroll"
28 | );
29 | const content = data
30 | .map(
31 | (item) => `
32 |
37 | `
38 | )
39 | .join("");
40 | producthuntSection.innerHTML = content;
41 | })
42 | .catch((error) => console.error(error));
43 | }
44 |
45 | function Medium() {
46 | fetch("https://api.hackertab.dev/data/v2/medium/javascript.json")
47 | .then((response) => response.json())
48 | .then((data) => {
49 | const mediumSection = document.querySelector("#medium .scroll");
50 | const content = data
51 | .map(
52 | (item) => `
53 |
58 | `
59 | )
60 | .join("");
61 | mediumSection.innerHTML = content;
62 | })
63 | .catch((error) => console.error(error));
64 | }
65 |
66 | function TabNews() {
67 | fetch("https://www.tabnews.com.br/api/v1/contents?strategy=relevant")
68 | .then((response) => response.json())
69 | .then((data) => {
70 | const tabnewsSection = document.querySelector("#tabnews .scroll");
71 | const content = data
72 | .map(
73 | (item) => `
74 |
79 | `
80 | )
81 | .join("");
82 | tabnewsSection.innerHTML = content;
83 | })
84 | .catch((error) => console.error(error));
85 | }
86 |
87 | function setCookie(name, value, days) {
88 | const date = new Date();
89 | date.setTime(date.getTime() + days * 24 * 60 * 60 * 1000);
90 | const expires = "expires=" + date.toUTCString();
91 | document.cookie = name + "=" + value + ";" + expires + ";path=/";
92 | }
93 |
94 | function getCookie(name) {
95 | const cookieName = name + "=";
96 | const cookies = document.cookie.split(";");
97 | for (let i = 0; i < cookies.length; i++) {
98 | let cookie = cookies[i];
99 | while (cookie.charAt(0) == " ") {
100 | cookie = cookie.substring(1);
101 | }
102 | if (cookie.indexOf(cookieName) == 0) {
103 | return cookie.substring(cookieName.length, cookie.length);
104 | }
105 | }
106 | return "";
107 | }
108 |
109 | // function DailyDev() {
110 | // fetch("https://cors-everywhere.onrender.com/https://dailydev.up.railway.app/")
111 | // .then((response) => response.json())
112 | // .then((data) => {
113 | // const dailydevSection = document.querySelector("#dailydev .scroll");
114 | // const content = data
115 | // .map(
116 | // (item) => `
117 | //
122 | // `
123 | // )
124 | // .join("");
125 | // dailydevSection.innerHTML = content;
126 |
127 | // // Salvar dados no cookie
128 | // setCookie("dailydevData", JSON.stringify(data), 1); // 1 dia de duração do cookie
129 | // })
130 | // .catch((error) => console.error(error));
131 | // }
132 |
133 | // Função para carregar dados do cookie e chamar a função DailyDev()
134 | function loadFromCookie() {
135 | const data = getCookie("dailydevData");
136 | if (data) {
137 | const parsedData = JSON.parse(data);
138 | const dailydevSection = document.querySelector("#dailydev .scroll");
139 | const content = parsedData
140 | .map(
141 | (item) => `
142 |
147 | `
148 | )
149 | .join("");
150 | dailydevSection.innerHTML = content;
151 | }
152 | }
153 |
154 | GithubTrending();
155 | Medium();
156 | ProductHunt();
157 | TabNews();
158 | // DailyDev();
159 |
--------------------------------------------------------------------------------
/styles/style.css:
--------------------------------------------------------------------------------
1 | * {
2 | margin: 0;
3 | padding: 0;
4 | box-sizing: border-box;
5 | }
6 |
7 | :root {
8 | --background-color: #303446;
9 | --text-color: #c6d0f5;
10 | --border: 1px solid #c6d0f5;
11 | --news-title: #51576d;
12 | }
13 |
14 | body {
15 | font-family: "Fira Code", monospace;
16 | color: var(--text-color);
17 | background-color: var(--background-color);
18 | margin: 1rem;
19 | overflow: hidden;
20 | }
21 |
22 | input {
23 | background-color: transparent;
24 | border: var(--border);
25 | border-radius: 1rem;
26 | padding: 0.5rem;
27 | text-align: center;
28 | color: var(--text-color);
29 | }
30 |
31 | a {
32 | color: var(--text-color);
33 | text-decoration: none;
34 | }
35 |
36 | i {
37 | color: var(--text-color);
38 | }
39 |
40 | nav {
41 | display: flex;
42 | align-items: center;
43 | justify-content: space-between;
44 | }
45 |
46 | main {
47 | display: flex;
48 | flex-wrap: wrap;
49 | flex-direction: column;
50 |
51 | height: 100vh;
52 | overflow-x: auto;
53 | overflow-y: hidden;
54 |
55 | scroll-snap-type: x mandatory;
56 | gap: 1rem;
57 | margin-bottom: 5rem;
58 | }
59 |
60 | main>section {
61 | scroll-snap-align: center;
62 | scroll-snap-stop: always;
63 | }
64 |
65 | .info-weather {
66 | display: flex;
67 | align-items: center;
68 | justify-content: center;
69 | gap: 0.1rem;
70 | font-size: 0.8rem;
71 | }
72 |
73 | .info-weather img {
74 | display: none;
75 | }
76 |
77 | .search {
78 | display: flex;
79 | justify-content: center;
80 | }
81 |
82 | .hand {
83 | display: flex;
84 | justify-content: center;
85 | padding: 2rem;
86 | animation: handMove 1.5s infinite;
87 | }
88 |
89 | .news {
90 | align-items: center;
91 | border: var(--border);
92 | border-radius: 1rem;
93 | overflow-y: scroll;
94 | margin-top: 0.5rem;
95 | width: 100%;
96 | max-height: 500px;
97 | }
98 |
99 | .news .title {
100 | display: flex;
101 | align-items: center;
102 | text-align: center;
103 | gap: 0.5rem;
104 | padding: 0.5rem;
105 | border-bottom: var(--border);
106 | }
107 |
108 | .title i,
109 | .title span {
110 | color: var(--news-title);
111 | font-size: 1.5rem;
112 | font-weight: 500;
113 | }
114 |
115 | .news>div {
116 | display: flex;
117 | justify-content: center;
118 | width: 100%;
119 | }
120 |
121 | .scroll {
122 | display: flex;
123 | flex-direction: column;
124 | overflow-y: auto;
125 | overflow-x: hidden;
126 | }
127 |
128 | .row-news {
129 | display: flex;
130 | flex-direction: column;
131 | width: 100%;
132 | border-bottom: var(--border);
133 | border-radius: 0.1rem;
134 | padding: 0.5rem;
135 | word-wrap: break-word;
136 | }
137 |
138 | .row-news:last-child {
139 | border-bottom: none;
140 | }
141 |
142 | .row-news p {
143 | font-size: 1rem;
144 | }
145 |
146 | footer a {
147 | display: flex;
148 | align-items: center;
149 | font-size: 1rem;
150 | text-align: center;
151 | justify-content: center;
152 | margin-top: 2rem;
153 | gap: 0.4rem;
154 | }
155 |
156 | .greeting-container {
157 | display: flex;
158 | flex-direction: column;
159 | justify-content: center;
160 | align-items: center;
161 | margin: 3rem 0;
162 | font-family: "Poppins", sans-serif;
163 | color: #a5adce;
164 | }
165 |
166 | .greeting-box {
167 | display: flex;
168 | gap: 0.2rem;
169 | text-align: center;
170 | }
171 |
172 | @keyframes handMove {
173 | 0% {
174 | transform: translateX(0);
175 | }
176 |
177 | 50% {
178 | transform: translateX(10px);
179 | }
180 |
181 | 100% {
182 | transform: translateX(-10px);
183 | }
184 | }
185 |
186 | @media (min-width: 300px) {
187 | main {
188 | height: 50vh;
189 | margin: 2rem 0 4rem 0;
190 | }
191 |
192 | main::-webkit-scrollbar {
193 | display: none;
194 | }
195 |
196 | nav {
197 | justify-content: center;
198 | }
199 |
200 | input,
201 | .logo {
202 | display: none;
203 | }
204 |
205 | .greeting-container {
206 | font-size: 0.9rem;
207 | gap: 0.5rem;
208 | text-align: center;
209 | margin: 2rem 0;
210 | }
211 |
212 | .greeting-box span {
213 | font-size: 1rem;
214 | }
215 |
216 | .hand {
217 | padding: 0.5rem 0;
218 | }
219 | }
220 |
221 | @media (min-width: 920px) {
222 | main::-webkit-scrollbar {
223 | display: none;
224 | }
225 |
226 | input {
227 | width: 20rem;
228 | }
229 |
230 | nav {
231 | justify-content: space-between;
232 | }
233 |
234 | input,
235 | .logo {
236 | display: block;
237 | }
238 |
239 | #hour,
240 | #previsao-tempo {
241 | display: block;
242 | }
243 |
244 | .info-weather {
245 | font-size: 0.9rem;
246 | }
247 |
248 | .info-weather img {
249 | display: block;
250 | }
251 | }
252 |
253 | @media (min-width: 1024px) {
254 | .container {
255 | margin: 1rem auto;
256 | width: 90%;
257 | }
258 |
259 | .greeting-container {
260 | margin: 4rem 0;
261 | }
262 |
263 | main {
264 | flex-direction: row;
265 | flex-wrap: nowrap;
266 | }
267 |
268 | input {
269 | width: 30rem;
270 | }
271 |
272 | .hand {
273 | display: none;
274 | }
275 |
276 | .logo {
277 | position: relative;
278 | width: 100px;
279 | }
280 |
281 | .logo img {
282 | position: absolute;
283 | right: 0;
284 | top: 50%;
285 | transform: translateY(-50%);
286 | }
287 | }
288 |
289 | @media (min-width: 2500px) {
290 | body {
291 | overflow: scroll;
292 | }
293 |
294 | .container {
295 | margin: 2rem auto;
296 | width: 90%;
297 | height: 90%;
298 | }
299 |
300 | main,
301 | .greeting-container,
302 | footer {
303 | margin: 10rem auto;
304 | }
305 | }
306 |
307 | /* ===== Scrollbar CSS ===== */
308 | /* Firefox */
309 | * {
310 | scrollbar-width: auto;
311 | scrollbar-color: #798595;
312 | }
313 |
314 | /* Chrome, Edge, and Safari */
315 | *::-webkit-scrollbar {
316 | width: 5px;
317 | }
318 |
319 | *::-webkit-scrollbar-track {
320 | background: transparent;
321 | }
322 |
323 | .news::-webkit-scrollbar-track {
324 | margin-block-start: 3rem;
325 | margin-block-end: 0.5rem;
326 | }
327 |
328 | *::-webkit-scrollbar-thumb {
329 | background-color: #798595;
330 | border-radius: 5px;
331 | }
332 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | DevNews
9 |
10 |
11 |
12 |
13 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
35 |
36 |
37 |
38 |
39 |
40 |
49 |
50 |
51 |
52 |
53 |
55 |
56 |
57 |
58 |
59 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
153 |
154 |
155 |
156 |

157 |
158 |
159 |
169 |
170 |
171 |
172 |
--------------------------------------------------------------------------------
/assets/scroll.svg:
--------------------------------------------------------------------------------
1 |
10 |
--------------------------------------------------------------------------------