Compare commits

...

32 commits
v1.0 ... master

Author SHA1 Message Date
87c056b690
Create README.md 2018-06-22 11:52:37 +02:00
866903b790
Aaand again (AppVeyor btw) 2018-02-12 20:37:33 +01:00
6854be7281
És megint 2018-02-12 20:34:11 +01:00
538fb1b47c
And again 2018-02-12 20:20:40 +01:00
df6d850131
És megint 2018-02-12 20:17:31 +01:00
2ff64cd7c4
Let's try this again 2018-02-12 20:15:12 +01:00
d3a987d526
ValueTuple frissítése, üres sornál hely. 2018-02-12 19:55:06 +01:00
074ed19236 Hely. szöveg felülre, óra elmarad és egyéb jav. 2017-10-03 17:00:02 +02:00
403fde579d Kisebb előrehaladás 2017-09-29 21:24:08 +02:00
f4fc6d9278 Csengetés format javítva, long press elkezdve 2017-09-28 23:09:54 +02:00
34ede81265 Internethibát nem ír ki majdnem semmiképpen
És a percet 01 perc helyett 1 percként írja ki
2017-09-26 22:07:38 +02:00
e5915c8082 A/B hét javítva, 09.01-től számolja már, egyéb jav.
- Kódanalízis, biztonsági attribútumok
- Hibakezelés javítva (internethiba, stb.)
2017-09-24 21:45:05 +02:00
e46a588a9f Óra eltolás, auto. fr.-t nem jelzi egy ideig, gyakori óranevek 2017-09-07 23:07:18 +02:00
55ab6467f4 Hibajavítások
- Perjel támogatása osztálynévben
- Ha olyan osztályt talál a helyettesítésekben, amit nem ismer, frissít
- Beállítja az utolsó frissítés idejét, ha sikeres volt
- Törli az extra sorokat, ha nincs most ott egy óra sem, de előtte volt
- Üres óranevek esetében kiírja az azonosítót (új óráknál)
2017-09-05 16:52:19 +02:00
3733f54fb9 Hibajavítások, az órarendet az API-ből veszi
- Az üres sor beszúró javítva
- A timer.Change javítva
- Az órarendet most már az API kezeli, kiválasztó metódusok hozzáadva
- Egyéb javítások
2017-03-28 22:17:57 +02:00
f8aeade139 Mégtöbb rövidítés, frissítés event kezelve, üres sorok berakva 2017-03-26 01:15:28 +01:00
95c72a2382 Frissítve C# 7.0-ra, tömörítések..., egyéb módosítások
A ConnectFaliure esetén javasolja, hogy indítsa újra az alkalmazást
2017-03-25 23:17:30 +01:00
45557da7bf Áthelyezés folytatva 2017-03-24 23:26:16 +01:00
318747b5bf Mozgatás a PCL-be elkezdve 2017-03-23 09:54:40 +01:00
33a7036ae8 Android függőség megszüntetve a PCL-ben 2017-03-23 08:30:13 +01:00
d70df804fd Javítások 2017-03-17 21:27:45 +01:00
22ae2f6612 Javítások. Már nem crashel. Valamiért.
Nem látom az összefüggést.
2017-03-15 00:20:04 +01:00
8d9c339f19 Hibajavítások, kisebb változtatások 2017-03-11 23:11:44 +01:00
de330e854c Beállítások menü és sötét/világos téma hozzáadva!
Több óra próbálkozással
De működik
2017-03-11 22:25:37 +01:00
665b3327f7 Mentés fejlesztve, áthelyezett óra kijelölése, javítások
- Minden mentett adat egy fájlba helyezve (data.json)
- Az áthelyezett órákat is ki lehet már jelölni
- Javítások
2017-03-11 16:11:08 +01:00
5a1c504f8c Javítások, a "van-e még óra" ellenőrzés javítva 2017-03-08 19:49:03 +01:00
0f2af248e0 Javítás javítva 2017-03-05 17:07:44 +01:00
58906b93b2 Órarendfrissítési bug javítva 2017-03-05 16:32:13 +01:00
ea8fb6d78f Javítások
- Most már csak akkor nyitja meg a fájlokat, ha elkezdi a mentést (adatvesztést elkerülendő)
- A helyettesítéseknél most már több osztály is támogatott egyszerre
- A tanárt beírja az eredeti órából áthelyezésnél
- Osztály egyenlőség a nullokra is működik
- Megnyitáskor kétszeres frissítés javítva
- Az utolsó frissítést akkor is beállítja, ha nem sikerült, így nem fog folyamatosan próbálkozni offline
- A következő óránál most már a helyettesített adatokat mutatja
- Óra közben a "Jelenlegi óra" feliratot mutatja, nem a "következő"-t
- Ha nincs több óra, a következő napra görget, nem a maira
2017-03-01 19:03:26 +01:00
789df17422 Javítások, fejlesztések
- Most már mindenképpen elmenti az órarendet és az osztályokat, így nem maradnak nyitva a fájlok
- A progress bar pozíciója javítva
- A részleteknél is pirossal jelzi a helyettesítéseket
- Jobb hibakezelés betöltéskor
- Nem jelzi a frissítést, ha gyorsan zajlik le - hasznos, ha a program offline próbál meg frissíteni
- Automatikusan frissíti a helyettesítéseket, ha már több, mint egy órája volt frissítve (a háttérben nem)
- A mai napot középpontba helyezi
- Egyéb
2017-02-28 20:37:15 +01:00
74966f3076 Helyettesítések megjelennek, javítások, stb.
- Egy óra kijelölése megszüntethető egy üres órahelyre kattintva
- Elmenti a helyettesítéseket
- Piros színnel jelzi azokat az órákat, ahol ideiglenes változás történt
- Rákattintva kiírja a változásokat is
- Most már nem írja ki a következő órát vasárnap
2017-02-26 02:11:18 +01:00
0c6e2c7e09 Helyettesítések elkezdve, javítások
- Le tudja tölteni és el tudja menteni a helyettesítéseket
- Csak az ehetieket (vagy hétvégén a jövőhetieket) veszi figyelembe
- Megállapítja, hogy A vagy B hét van-e
- Órarend duplikációs bug javítva (vissza gombbal való kilépéskor nem törli őket, de újra betöltötte megnyitáskor)
- Az aktuális naphoz görget minden előtérbe kerüléskor és frissítéskor
- Most már nem mutatja a "Nincs több óra ma" feliratot
- Az egész tartalom függőlegesen görgethető, nem külön-külön (elforgatott módban pl.)
2017-02-24 23:59:45 +01:00
32 changed files with 1053 additions and 397 deletions

View file

@ -1,33 +1,51 @@
using HtmlAgilityPack; using HtmlAgilityPack;
using Java.Lang; using Orarend.Events;
using SimpleTimerPortable;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Net; using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json; using System.Runtime.Serialization.Json;
using System.Security;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace Orarend namespace Orarend
{ {
public static class API [DataContract]
{ //TODO: Beállítások: Téma (sötét, világos) (Android; platformfüggő beállítások), Előre megadott egyedi nevek használata public class API
{ //TODO: Előre megadott egyedi nevek használata
internal static API példány = new API(); //TODO: FrissítésHa1ÓraEltelt() mentés
private API()
{
}
/// <summary>
/// A kulcs az óra azonosítója
/// </summary>
[DataMember(Order = 1)]
public Dictionary<string, ÓraTípus> típusok { get; private set; } = new Dictionary<string, ÓraTípus>();
[DataMember]
public Osztály[] osztályok { get; private set; } = new Osztály[0]; //Ez az initializáció csak akkor fut le, ha nem tölti be fájlból
[DataMember(Order = 2)]
public List<Órarend> órarendek { get; private set; } = new List<Órarend>();
[DataMember(Order = 3)]
public Settings beállítások { get; private set; } = new Settings();
/// <summary> /// <summary>
/// <para>Visszatér az osztályok listájával.</para> /// <para>Visszatér az osztályok listájával.</para>
/// <para>Lehet null, ha még nem volt sikeres <see cref="Frissítés"/>.</para> /// <para>Lehet null, ha még nem volt sikeres <see cref="Frissítés"/>.</para>
/// </summary> /// </summary>
/// <returns></returns> /// <returns></returns>
public static Osztály[] Osztályok { get; private set; } public static Osztály[] Osztályok { get => példány.osztályok; private set => példány.osztályok = value; }
public static List<Órarend> Órarendek { get; } = new List<Órarend>(); public static List<Órarend> Órarendek { get { return példány.órarendek; } }
public static Settings Beállítások { get; private set; } = new Settings(); public static Settings Beállítások { get => példány.beállítások; private set => példány.beállítások = value; }
public static List<Helyettesítés> Helyettesítések { get; } = new List<Helyettesítés>();
/// <summary> /// <summary>
/// Frissíti az osztálylistát és az eredeti órarendet, első megnyitásnál, és egy órarend hozzáadásánál/szerkesztésénél, majd hetente elegendő meghívni /// Frissíti az osztálylistát és az eredeti órarendet, első megnyitásnál, és egy órarend hozzáadásánál/szerkesztésénél, majd hetente elegendő meghívni
/// <param name="órarendstream">A file stream, ahova mentse az adatokat, hogy ne kelljen külön meghívni</param> /// <param name="stream">A file stream, ahova mentse az adatokat, hogy ne kelljen külön meghívni - Azért funkció, hogy elkerüljök az adatvesztést, mivel így csak a mentéskor nyitja meg</param>
/// <param name="osztálystream">A file stream, ahova mentse az adatokat, hogy ne kelljen külön meghívni</param>
/// </summary> /// </summary>
public static async Task Frissítés(Stream órarendstream, Stream osztálystream, Órarend ór = null) public static async Task Frissítés(Func<Stream> stream, Órarend ór = null)
{ {
Func<string, Task<HtmlDocument>> load = async (url) => Func<string, Task<HtmlDocument>> load = async (url) =>
{ {
@ -39,7 +57,7 @@ namespace Orarend
using (var sr = new StreamReader(resp.GetResponseStream())) using (var sr = new StreamReader(resp.GetResponseStream()))
{ {
const string trtd = @"(?:\s\w+=(?:\""|\')?(?:\w|[áéóüöőúű.:;])+(?:\""|\')?)*>(?!.+?\<table(?:\s\w+?=\""?\w+\""?)*\>.+?)(.+?)(?=<\1(?:\s\w+=(?:\""|\')?(?:\w|[áéóüöőúű.:;])+(?:\""|\')?)*>)"; const string trtd = @"(?:\s\w+=(?:\""|\')?(?:\w|[áéóüöőúű.:;])+(?:\""|\')?)*>(?!.+?\<table(?:\s\w+?=\""?\w+\""?)*\>.+?)(.+?)(?=<\1(?:\s\w+=(?:\""|\')?(?:\w|[áéóüöőúű.:;])+(?:\""|\')?)*>)";
string html = Regex.Replace(Regex.Replace(Regex.Replace(sr.ReadToEnd(), "<th([^>]*)>((?:\\w|[áéóüöőúű.])+)(?=<)(?!\\/)", "<th$1>$2</th>"), "<(tr)" + trtd, "<$1>$2</$1>"), "<(td)" + trtd, "<$1>$2</$1>"); string html = Regex.Replace(Regex.Replace(Regex.Replace(sr.ReadToEnd(), "<th([^>]*)>((?:\\w|[áéóüöőúű./])+)(?=<)(?!\\/)", "<th$1>$2</th>"), "<(tr)" + trtd, "<$1>$2</$1>"), "<(td)" + trtd, "<$1>$2</$1>");
doc.LoadHtml(html); doc.LoadHtml(html);
} }
}); });
@ -52,86 +70,164 @@ namespace Orarend
} }
Func<Órarend, Task> órarenda = async órarend => Func<Órarend, Task> órarenda = async órarend =>
{ {
var doc = await load("http://deri.enaplo.net/ajax/orarend/orarendoszt.php?p=" + Uri.EscapeDataString(órarend.Osztály.Azonosító)); var doc = await load("https://deri.enaplo.net/ajax/orarend/orarendoszt.php?p=" + órarend.Osztály.Azonosító);
await Task.Run(() => await Task.Run(() =>
{ {
Osztályok = doc.GetElementbyId("uok").ChildNodes.Where(node => node.HasAttributes).Select(node => new Osztály { Azonosító = node.GetAttributeValue("value", ""), Név = node.NextSibling.InnerText }).ToArray(); lock (Órarendek)
bool ahét = true;
foreach (var node in doc.GetElementbyId("oda").FirstChild.FirstChild.ChildNodes[1].ChildNodes)
{ {
switch (node.FirstChild.InnerText) Osztályok = doc.GetElementbyId("uok").ChildNodes.Where(node => node.HasAttributes).Select(node => new Osztály { Azonosító = node.GetAttributeValue("value", ""), Név = node.NextSibling.InnerText }).ToArray();
bool ahét = true;
int maxx = 0;
foreach (var node in doc.GetElementbyId("oda").FirstChild.FirstChild.ChildNodes[1].ChildNodes)
{ {
case "A": switch (node.FirstChild.InnerText)
ahét = true; {
break; case "A":
case "B": ahét = true;
ahét = false;
break;
default:
{
int x = int.Parse(node.FirstChild.InnerText) - 1;
órarend.Órakezdetek[x] = TimeSpan.Parse(node.FirstChild.Attributes["title"].Value.Split('-')[0].Trim());
for (int i = 0; i < 5; i++) //Napok
{
var óranode = node.ChildNodes[i + 1].FirstChild;
var óra = (ahét ? órarend.ÓrákAHét : órarend.ÓrákBHét)[i][x];
if (óranode.ChildNodes.Count == 0)
continue;
for (int j = 0; j < óranode.ChildNodes.Count; j += 6)
{
var csoport = óranode.ChildNodes[j].InnerText.TrimEnd(':');
if (csoport != "Egész osztály" && !órarend.Csoportok.Contains(csoport))
continue;
if (óra == null)
(ahét ? órarend.ÓrákAHét : órarend.ÓrákBHét)[i][x] = óra = new Óra();
óra.Csoportok = new string[] { csoport }; //Az állandó órarendben osztályonként csak egy csoport van egy órán
óra.Azonosító = óranode.ChildNodes[j + 2].InnerText;
óra.TeljesNév = óranode.ChildNodes[j + 2].Attributes["title"].Value;
óra.Terem = óranode.ChildNodes[j + 3].InnerText.Trim(' ', '(', ')');
óra.Tanár = new Tanár
{
Azonosító = óranode.ChildNodes[j + 4].InnerText,
Név = óranode.ChildNodes[j + 4].Attributes["title"].Value
};
break;
}
}
break; break;
} case "B":
ahét = false;
break;
default:
{
int x = int.Parse(node.FirstChild.InnerText) - 1, y = x - Beállítások.ÓraOffset;
maxx = x > maxx ? x : maxx;
if (y >= 0 && y < órarend.Órakezdetek.Length)
órarend.Órakezdetek[y] = TimeSpan.Parse(node.FirstChild.Attributes["title"].Value.Split('-')[0].Trim());
var órák = ahét ? órarend.ÓrákAHét : órarend.ÓrákBHét;
for (int i = 0; i < 5; i++) //Napok
{
var óranode = node.ChildNodes[i + 1].FirstChild;
var óra = órák[i][x];
if (óranode.ChildNodes.Count == 0)
{
órák[i][x] = null;
continue;
}
for (int j = 0; j < óranode.ChildNodes.Count; j += 6)
{
var csoport = óranode.ChildNodes[j].InnerText.TrimEnd(':');
if (csoport != "Egész osztály" && !órarend.Csoportok.Contains(csoport))
{
órák[i][x] = null;
continue;
}
if (óra == null)
órák[i][x] = óra = new Óra();
óra.Csoportok = new string[] { csoport }; //Az állandó órarendben osztályonként csak egy csoport van egy órán
óra.Azonosító = óranode.ChildNodes[j + 2].InnerText;
óra.TeljesNév = óranode.ChildNodes[j + 2].Attributes["title"].Value;
óra.Terem = óranode.ChildNodes[j + 3].InnerText.Trim(' ', '(', ')');
óra.Tanár = new Tanár
{
Azonosító = óranode.ChildNodes[j + 4].InnerText,
Név = óranode.ChildNodes[j + 4].Attributes["title"].Value
};
break;
}
}
break;
}
}
} }
for (int i = maxx + 1; i < 16; i++) //Órák
for (int j = 0; j < 5; j++) //Napok
órarend.Órák[j][i] = null; //Kitörli a küldött órarendben nem szereplő órákat
} }
Thread.Sleep(10);
}); });
await Task.Delay(10);
}; };
if (ór == null) if (ór == null)
foreach (var órarend in Órarendek) foreach (var órarend in Órarendek)
await órarenda(órarend); await órarenda(órarend);
else else
await órarenda(ór); await órarenda(ór);
ÓrarendMentés(órarendstream); Mentés(stream());
OsztályMentés(osztálystream);
} }
/// <summary> /// <summary>
/// Frissíti a helyettesítéseket, naponta, indításkor vagy gombnyommásra frissítse (minden nap az első előtérbe kerüléskor) /// Frissíti a helyettesítéseket, naponta, indításkor vagy gombnyommásra frissítse (minden nap az első előtérbe kerüléskor)
/// <param name="s">A file stream, ahova mentse az adatokat, hogy ne kelljen külön meghívni</param>
/// </summary> /// </summary>
public static async Task HelyettesítésFrissítés(Stream s) /// <param name="stream">A file stream, ahova mentse az adatokat, hogy ne kelljen külön meghívni - Azért funkció, hogy elkerüljök az adatvesztést, mivel így csak a mentéskor nyitja meg</param>
public static async Task<bool> HelyettesítésFrissítés(Func<Stream> stream)
{ {
if (Órarendek.Count == 0 || Osztályok.Length == 0)
return false;
HtmlDocument doc = new HtmlDocument(); HtmlDocument doc = new HtmlDocument();
var req = WebRequest.CreateHttp("http://deri.enaplo.net/ajax/print/htlista.php"); var req = WebRequest.CreateHttp("http://deri.enaplo.net/ajax/print/htlista.php");
var resp = await req.GetResponseAsync(); var resp = await req.GetResponseAsync();
await Task.Run(() => await Task.Run(() =>
{ {
using (var sr = new StreamReader(resp.GetResponseStream())) lock (Órarendek)
doc.LoadHtml(sr.ReadToEnd()); {
}); //TODO using (var sr = new StreamReader(resp.GetResponseStream()))
doc.LoadHtml(sr.ReadToEnd());
foreach (var órarend in Órarendek)
órarend.Helyettesítések.Clear();
foreach (var node in doc.DocumentNode.ChildNodes[2].ChildNodes[1].ChildNodes)
{
DateTime dátum = DateTime.Parse(node.ChildNodes[0].InnerText.Substring(0, node.ChildNodes[0].InnerText.Length - 4));
int hét = CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(dátum, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday);
if (hét != Hét)
continue;
byte óraszám = byte.Parse(node.ChildNodes[1].InnerText);
var osztályok = node.ChildNodes[2].InnerText.Split(new string[] { ", " }, StringSplitOptions.None);
foreach (string osztálynév in osztályok)
{
Osztály osztály = Osztályok.SingleOrDefault(o => o.Azonosító.Contains(osztálynév));
if (osztály == null)
{
var x = new InvalidOperationException($"A helyettesítésekben szereplő osztály \"{osztálynév}\" nem található.");
x.Data.Add("OERROR", "CLS_NOT_FOUND");
throw x;
}
var csoportok = node.ChildNodes[3].InnerText;
int névindex = csoportok.IndexOf(osztálynév);
int végeindex = csoportok.IndexOf(")", névindex >= 0 ? névindex : 0);
string csoport = osztályok.Length == 1 ? csoportok : csoportok.Substring(névindex + osztálynév.Length + 1, végeindex - névindex - osztálynév.Length - 1);
string óraaz = node.ChildNodes[4].InnerText;
string terem = node.ChildNodes[5].InnerText.Split(new string[] { " -> " }, StringSplitOptions.None).Last(); //Mindig az új termet tárolja el, ha változott
string tanár = node.ChildNodes[7].InnerText;
string[] megj = node.ChildNodes[8].InnerText.Split(' ');
string óranév = node.ChildNodes[9].InnerText;
DayOfWeek újnap = dátum.DayOfWeek;
byte újsorszám = óraszám;
if (megj.Length > 2)
{
újnap = DateTime.Parse(megj[1]).DayOfWeek;
újsorszám = byte.Parse(megj[3].Trim('.'));
}
foreach (var órarend in (csoport == "Egész osztály" ? Órarendek : Órarendek.Where(ór => ór.Csoportok.Contains(csoport))).Where(ór => ór.Osztály == osztály))
{
if (tanár == "")
tanár = órarend.Órák[(int)dátum.DayOfWeek - 1][óraszám - 1]?.Tanár.Név ?? "";
var helyettesítés = new Helyettesítés { EredetiNap = dátum.DayOfWeek, EredetiSorszám = óraszám, ÚjÓra = tanár == "elmarad" ? null : new Óra { Azonosító = óraaz, Csoportok = new string[] { csoport }, Terem = terem, Tanár = new Tanár { Név = tanár }, TeljesNév = óranév }, ÚjNap = újnap, ÚjSorszám = újsorszám };
órarend.Helyettesítések.Add(helyettesítés);
}
}
}
}
Mentés(stream());
utolsófrissítésplusz1óra = DateTime.Now + new TimeSpan(1, 0, 0); //Mindenképpen állítsa be, hogy ne írja folyamatosan a hibát
});
return true;
} }
private static T betöltés<T>(Stream s) [OnDeserializing]
private void betöltés(StreamingContext context) => példány = this; //Az órák azonosítójának beállításakor szükséges már
/// <summary>
/// Betölti az adatokat, ha még nincsenek betöltve
/// </summary>
/// <param name="s">A stream, ahonnan betöltse az adatokat</param>
/// <param name="hibánál">Megadja, mi történjen egy hiba esetén</param>
/// <returns>Elvégezte-e a betöltést</returns>
public static bool Betöltés(Stream s, Action<Exception> hibánál)
{ {
using (s) using (s)
{ {
if (!!!betöltés())
return false;
using (var ms = new MemoryStream()) using (var ms = new MemoryStream())
{ {
s.CopyTo(ms); s.CopyTo(ms);
@ -140,69 +236,158 @@ namespace Orarend
try try
{ {
ms.Seek(0, SeekOrigin.Begin); ms.Seek(0, SeekOrigin.Begin);
var serializer = new DataContractJsonSerializer(typeof(T)); var serializer = new DataContractJsonSerializer(typeof(API));
return (T)serializer.ReadObject(ms); serializer.ReadObject(ms); //A példányt beállítja, mikor elkezdi, nem várja meg, hogy végezzen (betöltés())
return true;
} }
catch catch (Exception e)
{ {
return default(T); hibánál(e);
return Betöltés();
} }
} }
return default(T); else return false;
} }
} }
} } //TODO: Tényleges órarendből állapítsa meg azt is, hogyha egyáltalán nincs ott egy óra, és máshol sincs, és ezt írja ki
public static void ÓrarendBetöltés(Stream s) /// <summary>
/// Betölti az alapértelemzett értékeket
/// <returns>Elvégezte-e a betöltést</returns>
/// </summary>
public static bool Betöltés()
{ {
Órarendek.AddRange(betöltés<Órarend[]>(s) ?? new Órarend[0]); if (!betöltés())
return false;
példány = new API();
return true;
} }
public static void OsztályBetöltés(Stream s) private static Timer timer;
private static bool betöltés()
{ {
Osztályok = betöltés<Osztály[]>(s) ?? new Osztály[0]; if (!!(Órarendek.Count > 0 || Osztályok?.Length > 0 || timer != null))
return false;
timer = new Timer(CsengőTimer, null, new TimeSpan(0, 0, 0, 0, 100), new TimeSpan(0, 0, 5));
return true;
} }
public static void BeállításBetöltés(Stream s) public static void Mentés(Stream s)
{
Beállítások = betöltés<Settings>(s);
}
public static void HelyettesítésBetöltés(Stream s)
{ //TODO: Tényleges órarendből állapítsa meg azt is, hogyha egyáltalán nincs ott egy óra, és máshol sincs, és ezt írja ki
Helyettesítések.AddRange(betöltés<Helyettesítés[]>(s) ?? new Helyettesítés[0]);
}
private static void mentés<T>(Stream s, T obj)
{ {
using (s) using (s)
if (példány != null)
new DataContractJsonSerializer(példány.GetType()).WriteObject(s, példány);
}
/// <summary>
/// Visszatér a megjelenítendő héttel. Ez megegyezik a tényleges héttel, kivéve hétvégén, amikor a következő
/// </summary>
public static int Hét
{
get
{ {
if (obj != null) int jelenlegihét = napbólhét(DateTime.Today);
{ if (DateTime.Today.DayOfWeek > DayOfWeek.Friday || DateTime.Today.DayOfWeek == DayOfWeek.Sunday)
var serializer = new DataContractJsonSerializer(typeof(T)); jelenlegihét++;
serializer.WriteObject(s, obj); return jelenlegihét;
}
} }
} }
public static void ÓrarendMentés(Stream s) private static int napbólhét(DateTime nap) => CultureInfo.InvariantCulture.Calendar.GetWeekOfYear(nap, CalendarWeekRule.FirstFullWeek, DayOfWeek.Monday);
public static bool AHét { get => Hét % 2 == napbólhét(new DateTime(DateTime.Today.Year - (DateTime.Today.Month < 8 ? 1 : 0), 9, 1)) % 2; }
public static bool Fókusz
{ {
mentés(s, Órarendek.ToArray()); set
{
if (value)
{
timer = timer.Change(new TimeSpan(0, 0, 0), new TimeSpan(0, 0, 5));
frissítésHa1ÓraEltelt();
}
else
timer.Cancel();
}
} }
private static void OsztályMentés(Stream s) private static DateTime utolsófrissítésplusz1óra = DateTime.MinValue;
public static event EventHandler<FrissítésEventArgs> Frissítéskor;
public class FrissítésEventArgs : EventArgs { public bool Siker { get; set; } = false; }
private static void frissítésHa1ÓraEltelt()
{ {
mentés(s, Osztályok); if (utolsófrissítésplusz1óra > DateTime.Now)
return;
var args = new FrissítésEventArgs();
Frissítéskor?.Invoke(példány, args);
if (args.Siker)
utolsófrissítésplusz1óra = DateTime.Now + new TimeSpan(1, 0, 0);
} }
public static void BeállításMentés(Stream s) public static DayOfWeek MaiNap
{ {
mentés(s, Beállítások); get
{
var x = DateTime.Today.DayOfWeek;
if (nincstöbbóra) x++;
return x > DayOfWeek.Saturday || x == DayOfWeek.Sunday ? DayOfWeek.Monday : x;
}
} }
private static void HelyettesítésMentés(Stream s) public static (Helyettesítés innen, Helyettesítés ide) HelyettesítésInnenIde(Órarend órarend, int i, int j) =>
(órarend.Helyettesítések.FirstOrDefault(h => (int)h.EredetiNap == i + 1 && h.EredetiSorszám == j + 1),
órarend.Helyettesítések.FirstOrDefault(h => (int)h.ÚjNap == i + 1 && h.ÚjSorszám == j + 1 && h.ÚjÓra != null));
//Ha az eredeti óra elmarad, és ide lesz helyezve egy másik, az áthelyezést mutassa
public static Órarend Órarend { get; private set; }
public static void ÓrarendKiválasztás(int position) { Órarend = Órarendek[position]; CsengőTimer(null); }
public static void ÓrarendKiválasztásTörlése() { Órarend = null; CsengőTimer(null); }
private static bool nincstöbbóra = false;
public static event EventHandler<TimerEventArgs> CsengőTimerEvent;
private static void CsengőTimer(object state) => CsengőTimerEvent?.Invoke(példány, CsengőTimer());
private static TimerEventArgs CsengőTimer()
{ {
mentés(s, Helyettesítések.ToArray()); if (Órarend == null)
return new TimerEventArgs(null, "Nincs órarend kiválasztva");
var most = DateTime.Now - DateTime.Today;
//var most = new TimeSpan(12, 46, 0);
bool talált = false;
if (Órarend.Órakezdetek[Beállítások.ÓraOffset] == TimeSpan.Zero) //Még nincsenek beállítva a kezdetek
return new TimerEventArgs(null, "Betöltés");
string kezdveg = null, kovora = null;
for (int i = 0; i < Órarend.Órakezdetek.Length - 1; i++)
{
var vége = Órarend.Órakezdetek[i].Add(new TimeSpan(0, 45, 0));
bool becsengetés;
int x = (int)DateTime.Today.DayOfWeek - 1;
Óra óra;
var (innen, ide) = HelyettesítésInnenIde(Órarend, x, i);
Func<TimeSpan, string> óraperc = ts => ts.Hours > 0 ? ts.ToString("h\\ómm\\p") : ts.ToString("%m") + " perc";
if (x != -1 && x < 6 && (óra = ide != null ? ide.ÚjÓra : innen != null ? innen.EredetiNap != innen.ÚjNap || innen.EredetiSorszám != innen.ÚjSorszám ? null : innen.ÚjÓra : Órarend.Órák[x][i]) != null)
{ //-1: Vasárnap
if (most > Órarend.Órakezdetek[i])
{
if (most < vége)
{
kezdveg = "Kicsengetés: " + óraperc(vége - most);
talált = true;
becsengetés = false;
}
else
continue;
}
else
{
kezdveg = "Becsengetés: " + óraperc(Órarend.Órakezdetek[i] - most);
talált = true;
becsengetés = true;
}
kovora = (becsengetés ? "Következő" : "Jelenlegi") + " óra: " + óra.EgyediNév + "\n" + óra.Terem + "\n" + óra.Tanár.Név + "\n" + óra.Csoportok.Aggregate((a, b) => a + ", " + b);
break;
}
}
nincstöbbóra = !talált;
return new TimerEventArgs(kovora, kezdveg);
} }
} }
} }

View file

@ -0,0 +1,25 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Orarend.Events
{
public class TimerEventArgs : EventArgs
{
/// <summary>
/// Lehet null
/// </summary>
public string KövetkezőÓra { get; }
/// <summary>
/// Lehet null
/// </summary>
public string HátralévőIdő { get; }
public TimerEventArgs(string kövóra, string hátralévőidő)
{
KövetkezőÓra = kövóra;
HátralévőIdő = hátralévőidő;
}
}
}

View file

@ -11,13 +11,11 @@ namespace Orarend
public class Helyettesítés public class Helyettesítés
{ {
[DataMember] [DataMember]
public byte EredetiNap { get; set; } public DayOfWeek EredetiNap { get; set; }
[DataMember] [DataMember]
public byte EredetiSorszám { get; set; } public byte EredetiSorszám { get; set; }
[DataMember] [DataMember]
public Óra EredetiÓra { get; set; } public DayOfWeek ÚjNap { get; set; }
[DataMember]
public byte ÚjNap { get; set; }
[DataMember] [DataMember]
public byte ÚjSorszám { get; set; } public byte ÚjSorszám { get; set; }
[DataMember] [DataMember]

View file

@ -2,7 +2,7 @@
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" /> <Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup> <PropertyGroup>
<MinimumVisualStudioVersion>11.0</MinimumVisualStudioVersion> <MinimumVisualStudioVersion>10.0</MinimumVisualStudioVersion>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration> <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform> <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{93C1582B-AD0F-44EC-BB69-02EE1ADFC0DD}</ProjectGuid> <ProjectGuid>{93C1582B-AD0F-44EC-BB69-02EE1ADFC0DD}</ProjectGuid>
@ -13,8 +13,8 @@
<DefaultLanguage>en-US</DefaultLanguage> <DefaultLanguage>en-US</DefaultLanguage>
<FileAlignment>512</FileAlignment> <FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids> <ProjectTypeGuids>{786C830F-07A1-408B-BD7F-6EE04809D6DB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<TargetFrameworkProfile>Profile111</TargetFrameworkProfile> <TargetFrameworkProfile>Profile44</TargetFrameworkProfile>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion> <TargetFrameworkVersion>v4.6</TargetFrameworkVersion>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols> <DebugSymbols>true</DebugSymbols>
@ -33,24 +33,28 @@
<ErrorReport>prompt</ErrorReport> <ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel> <WarningLevel>4</WarningLevel>
</PropertyGroup> </PropertyGroup>
<PropertyGroup>
<SignAssembly>false</SignAssembly>
</PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="API.cs" /> <Compile Include="API.cs" />
<Compile Include="Events\TimerEventArgs.cs" />
<Compile Include="Helyettesítés.cs" /> <Compile Include="Helyettesítés.cs" />
<Compile Include="Osztály.cs" /> <Compile Include="Osztály.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Settings.cs" /> <Compile Include="Settings.cs" />
<Compile Include="Tanár.cs" /> <Compile Include="Tanár.cs" />
<Compile Include="Timer.cs" />
<Compile Include="Óra.cs" /> <Compile Include="Óra.cs" />
<Compile Include="Órarend.cs" /> <Compile Include="Órarend.cs" />
<Compile Include="ÓraTípus.cs" /> <Compile Include="ÓraTípus.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Reference Include="HtmlAgilityPack, Version=1.4.9.4, Culture=neutral, processorArchitecture=MSIL"> <Reference Include="HtmlAgilityPack, Version=1.4.9.5, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\packages\HtmlAgilityPack.1.4.9.4\lib\portable-net45+netcore45+wpa81+wp8+MonoAndroid+MonoTouch\HtmlAgilityPack.dll</HintPath> <HintPath>..\packages\HtmlAgilityPack.1.4.9.5\lib\portable-net45+netcore45+wp8+MonoAndroid+MonoTouch\HtmlAgilityPack.dll</HintPath>
<Private>True</Private>
</Reference> </Reference>
<Reference Include="Mono.Android"> <Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51">
<HintPath>C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\MonoAndroid\v6.0\Mono.Android.dll</HintPath> <HintPath>..\packages\System.ValueTuple.4.4.0\lib\portable-net40+sl4+win8+wp8\System.ValueTuple.dll</HintPath>
</Reference> </Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>

View file

@ -18,14 +18,12 @@ namespace Orarend
{ {
} }
public override string ToString() public override string ToString() => Név;
{
return Név;
}
public bool Equals(Osztály other) public bool Equals(Osztály other) => Azonosító == other?.Azonosító;
{ public static bool operator==(Osztály a, Osztály b) => a?.Equals(b) ?? (object)b == null;
return Azonosító == other.Azonosító; public static bool operator!=(Osztály a, Osztály b) => !(a == b);
} public override bool Equals(object obj) => obj is Osztály ? Equals(obj as Osztály) : base.Equals(obj);
public override int GetHashCode() => Azonosító.GetHashCode();
} }
} }

View file

@ -2,6 +2,7 @@
using System.Reflection; using System.Reflection;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
using System.Security;
// General Information about an assembly is controlled through the following // General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information // set of attributes. Change these attribute values to modify the information
@ -15,6 +16,7 @@ using System.Runtime.InteropServices;
[assembly: AssemblyTrademark("")] [assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")] [assembly: AssemblyCulture("")]
[assembly: NeutralResourcesLanguage("en")] [assembly: NeutralResourcesLanguage("en")]
[assembly: SecurityTransparent]
// Version information for an assembly consists of the following four values: // Version information for an assembly consists of the following four values:
// //

View file

@ -7,11 +7,9 @@ using System.Threading.Tasks;
namespace Orarend namespace Orarend
{ {
[DataContract] [DataContract] //
public class Settings public class Settings
{ {
[DataMember]
public bool DarkTheme { get; set; }
public void UseCommonNames() public void UseCommonNames()
{ {
set("mateme", "Matek"); set("mateme", "Matek");
@ -20,6 +18,7 @@ namespace Orarend
set(";prggy", "Programozás gyakorlat"); set(";prggy", "Programozás gyakorlat");
set("testns", "Tesi"); set("testns", "Tesi");
set("tapism", "Töri"); set("tapism", "Töri");
set("torten", "Töri");
set("matema", "Matek"); set("matema", "Matek");
set("bioege", "Biosz"); set("bioege", "Biosz");
set("foldra", "Föci"); set("foldra", "Föci");
@ -31,5 +30,8 @@ namespace Orarend
if (ÓraTípus.Típusok.ContainsKey(id)) if (ÓraTípus.Típusok.ContainsKey(id))
ÓraTípus.Típusok[id].EgyediNév = name; ÓraTípus.Típusok[id].EgyediNév = name;
} }
[DataMember]
public sbyte ÓraOffset { get; set; } = 0;
} }
} }

48
Orarend/Timer.cs Normal file
View file

@ -0,0 +1,48 @@
using System;
using System.Threading;
using System.Threading.Tasks;
namespace SimpleTimerPortable
{
internal delegate void TimerCallback(object state);
internal sealed class Timer : CancellationTokenSource, IDisposable
{
public Timer(TimerCallback callback, object state, TimeSpan dueTime, TimeSpan period)
{
this.callback = callback;
this.state = state;
start(dueTime, period);
}
private TimerCallback callback;
private object state;
private void start(TimeSpan dueTime, TimeSpan period)
{
Task.Delay(dueTime, Token).ContinueWith(async (t, s) =>
{
var tuple = (Tuple<TimerCallback, object>)s;
while (true)
{
if (IsCancellationRequested)
break;
await Task.Run(() => tuple.Item1(tuple.Item2));
await Task.Delay(period);
}
}, Tuple.Create(callback, state), CancellationToken.None,
TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion,
TaskScheduler.Default);
}
public new void Dispose() { base.Cancel(); }
public Timer Change(TimeSpan dueTime, TimeSpan period)
{
var timer = new Timer(callback, state, dueTime, period);
this.Dispose();
return timer;
}
}
}

View file

@ -1,4 +1,8 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="HtmlAgilityPack" version="1.4.9.4" targetFramework="portable45-net45+win8+wpa81" /> <package id="HtmlAgilityPack" version="1.4.9.5" targetFramework="portable45-net45+wp8" />
<package id="System.Collections" version="4.3.0" targetFramework="portable46-net451+win81" />
<package id="System.Resources.ResourceManager" version="4.3.0" targetFramework="portable46-net451+win81" />
<package id="System.Runtime" version="4.3.0" targetFramework="portable46-net451+win81" />
<package id="System.ValueTuple" version="4.4.0" targetFramework="portable46-net451+win81" />
</packages> </packages>

View file

@ -10,7 +10,6 @@ namespace Orarend
[DataContract] [DataContract]
public class Óra public class Óra
{ {
[DataMember]
private ÓraTípus Típus { get; set; } private ÓraTípus Típus { get; set; }
[DataMember] [DataMember]
public Tanár Tanár { get; set; } public Tanár Tanár { get; set; }
@ -22,6 +21,10 @@ namespace Orarend
[DataMember] [DataMember]
public string[] Csoportok { get; set; } public string[] Csoportok { get; set; }
[DataMember]
public bool ManuálisanHozzáadott { get; set; }
[DataMember]
public string Azonosító public string Azonosító
{ {
get get

View file

@ -7,7 +7,21 @@ namespace Orarend
public class ÓraTípus public class ÓraTípus
{ {
[DataMember] [DataMember]
public string TeljesNév { get; set; } private string teljesnév;
public string TeljesNév
{
get
{
return teljesnév;
}
set
{
if ((value?.Trim()?.Length ?? 0) == 0)
teljesnév = "(" + Azonosító + ")";
else
teljesnév = value;
}
}
[DataMember] [DataMember]
public string Azonosító { get; set; } public string Azonosító { get; set; }
[DataMember] [DataMember]
@ -16,6 +30,6 @@ namespace Orarend
/// <summary> /// <summary>
/// A kulcs az óra azonosítója /// A kulcs az óra azonosítója
/// </summary> /// </summary>
public static Dictionary<string, ÓraTípus> Típusok { get; } = new Dictionary<string, ÓraTípus>(); public static Dictionary<string, ÓraTípus> Típusok { get { return API.példány.típusok; } }
} }
} }

View file

@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.Serialization; using System.Runtime.Serialization;
using System.Security;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -10,18 +11,21 @@ namespace Orarend
[DataContract] [DataContract]
public class Órarend public class Órarend
{ {
[DataMember]
internal Óra[][] ÓrákAHét { get; private set; } = new Óra[6][] { new Óra[16], new Óra[16], new Óra[16], new Óra[16], new Óra[16], new Óra[16] };
[DataMember]
internal Óra[][] ÓrákBHét { get; private set; } = new Óra[6][] { new Óra[16], new Óra[16], new Óra[16], new Óra[16], new Óra[16], new Óra[16] }; //Multidimensional arrays are not supported (serialization)
/// <summary> /// <summary>
/// <para>Egy 6x16 2D tömb, az első koordináta a nap indexe, a második az óráé. Az értékek lehetnek null-ok, ha nincs óra az adott időpontban</para> /// <para>Egy 6x16 2D tömb, az első koordináta a nap indexe, a második az óráé. Az értékek lehetnek null-ok, ha nincs óra az adott időpontban</para>
/// <para>Egy <see cref="API.Frissítés"/> hívás állítja be az órákat</para> /// <para>Egy <see cref="API.Frissítés"/> hívás állítja be az órákat</para>
/// </summary> /// </summary>
[DataMember] public Óra[][] Órák
public Óra[][] ÓrákAHét { get; private set; } = new Óra[6][] { new Óra[16], new Óra[16], new Óra[16], new Óra[16], new Óra[16], new Óra[16] }; {
/// <summary> get
/// <para>Egy 6x16 2D tömb, az első koordináta a nap indexe, a második az óráé. Az értékek lehetnek null-ok, ha nincs óra az adott időpontban</para> {
/// <para>Egy <see cref="API.Frissítés"/> hívás állítja be az órákat</para> return API.AHét ? ÓrákAHét : ÓrákBHét;
/// </summary> }
[DataMember] }
public Óra[][] ÓrákBHét { get; private set; } = new Óra[6][] { new Óra[16], new Óra[16], new Óra[16], new Óra[16], new Óra[16], new Óra[16] }; //Multidimensional arrays are not supported (serialization)
/// <summary> /// <summary>
/// <para>Egy <see cref="API.Frissítés"/> hívás állítja be</para> /// <para>Egy <see cref="API.Frissítés"/> hívás állítja be</para>
/// </summary> /// </summary>
@ -36,6 +40,8 @@ namespace Orarend
public TimeSpan[] Órakezdetek { get; private set; } = new TimeSpan[16]; //A private set kell a serialization miatt public TimeSpan[] Órakezdetek { get; private set; } = new TimeSpan[16]; //A private set kell a serialization miatt
[DataMember] [DataMember]
public string[] Csoportok { get; set; } public string[] Csoportok { get; set; }
[DataMember]
public List<Helyettesítés> Helyettesítések { get; private set; } = new List<Helyettesítés>();
/// <summary> /// <summary>
/// Létrehoz egy új órarendet /// Létrehoz egy új órarendet

View file

@ -0,0 +1,28 @@
using Android.App;
using Android.OS;
using Android.Preferences;
using System.Security;
namespace OrarendAndroidApp
{
public class ActivityBase : Activity
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetTheme(this);
}
public static void SetTheme(Activity activity)
{
var settings = PreferenceManager.GetDefaultSharedPreferences(activity);
bool darktheme = settings.GetBoolean("pref_theme", false);
if (activity is ActivityBase ab)
ab.DarkTheme = darktheme;
activity.SetTheme(darktheme ? Android.Resource.Style.ThemeDeviceDefault : Android.Resource.Style.ThemeDeviceDefaultLight);
}
public bool DarkTheme;
}
}

View file

@ -11,11 +11,13 @@ using Android.Views;
using Android.Widget; using Android.Widget;
using Orarend; using Orarend;
using Android.Graphics; using Android.Graphics;
using Android.Preferences;
using System.Security;
namespace OrarendAndroidApp namespace OrarendAndroidApp
{ {
[Activity(Label = "AddActivity", Theme = "@android:style/Theme.Holo.Light")] [Activity(Label = "AddActivity", Theme = "@android:style/Theme.Holo.Light")]
public class EditActivity : Activity public class EditActivity : ActivityBase
{ {
private bool add; private bool add;
private int index; private int index;
@ -44,6 +46,9 @@ namespace OrarendAndroidApp
osztálySpinner.SetSelection(ix); osztálySpinner.SetSelection(ix);
FindViewById<EditText>(Resource.Id.csoportokEditText).Text = órarend.Csoportok.Aggregate((a, b) => a + " " + b); FindViewById<EditText>(Resource.Id.csoportokEditText).Text = órarend.Csoportok.Aggregate((a, b) => a + " " + b);
} }
else
FindViewById<EditText>(Resource.Id.névEditText).Text = "Órarend";
osztálySpinner.LayoutParameters = new TableRow.LayoutParams((osztálySpinner.Parent as View)?.Width - (osztálySpinner.Parent as ViewGroup)?.GetChildAt(0)?.Width ?? TableRow.LayoutParams.MatchParent, TableRow.LayoutParams.WrapContent); //TODO
FindViewById<Button>(Resource.Id.saveButton).Click += SaveButtonClick; FindViewById<Button>(Resource.Id.saveButton).Click += SaveButtonClick;
var deleteButton = FindViewById<Button>(Resource.Id.deleteButton); var deleteButton = FindViewById<Button>(Resource.Id.deleteButton);
if (add) if (add)
@ -66,7 +71,7 @@ namespace OrarendAndroidApp
intent.PutExtra("deleted", true); intent.PutExtra("deleted", true);
((AlertDialog)s).Dismiss(); ((AlertDialog)s).Dismiss();
((AlertDialog)s).Dispose(); ((AlertDialog)s).Dispose();
API.ÓrarendMentés(OpenFileOutput("orarend", FileCreationMode.Private)); API.Mentés(OpenFileOutput(MainActivity.DATA_FILENAME, FileCreationMode.Private));
SetResult(Result.Ok, intent); SetResult(Result.Ok, intent);
Finish(); Finish();
}).SetNegativeButton("Nem", (s, ea) => }).SetNegativeButton("Nem", (s, ea) =>
@ -90,7 +95,7 @@ namespace OrarendAndroidApp
} }
else else
API.Órarendek.Add(new Órarend(név, osztály, csoportok)); API.Órarendek.Add(new Órarend(név, osztály, csoportok));
API.ÓrarendMentés(OpenFileOutput("orarend", FileCreationMode.Private)); API.Mentés(OpenFileOutput(MainActivity.DATA_FILENAME, FileCreationMode.Private));
SetResult(Result.Ok, Intent); SetResult(Result.Ok, Intent);
Finish(); Finish();
} }

View file

@ -8,52 +8,58 @@ using Android.OS;
using Orarend; using Orarend;
using System.Linq; using System.Linq;
using Android.Graphics; using Android.Graphics;
using Java.Lang;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading.Tasks; using System.Threading.Tasks;
using System.Threading; using System.Threading;
using System.IO; using System.IO;
using System.Net; using System.Net;
using Android.Preferences;
using Orarend.Events;
using System.Security;
namespace OrarendAndroidApp namespace OrarendAndroidApp
{ {
[Activity(Label = "Órarend", MainLauncher = true, Theme = "@android:style/Theme.Holo.Light")] [Activity(Label = "Órarend", MainLauncher = true, Theme = "@android:style/Theme.DeviceDefault")]
public class MainActivity : Activity public class MainActivity : ActivityBase
{ {
private Handler handler; private Handler handler;
private Órarend órarend;
private const int EDIT_ADD_ACT_REQUEST = 1; private const int EDIT_ADD_ACT_REQUEST = 1;
private const int SETTINGS_ACT_REQUEST = 2;
public const string DATA_FILENAME = "data.json";
protected override void OnCreate(Bundle bundle) protected override void OnCreate(Bundle bundle)
{ {
AndroidEnvironment.UnhandledExceptionRaiser += AndroidEnvironment_UnhandledExceptionRaiser;
base.OnCreate(bundle); base.OnCreate(bundle);
SetContentView(Resource.Layout.MainLayout); SetContentView(Resource.Layout.MainLayout);
ActionBar.SetDisplayShowTitleEnabled(false); ActionBar.SetDisplayShowTitleEnabled(false);
ActionBar.CustomView = FindViewById<Spinner>(Resource.Id.spinner);
handler = new Handler(); handler = new Handler();
string[] list = FileList(); string[] list = FileList();
if (list.Contains("beallitasok")) if (list.Contains(DATA_FILENAME)
API.BeállításBetöltés(OpenFileInput("beallitasok")); ? API.Betöltés(OpenFileInput(DATA_FILENAME), e => Hiba("Hiba az adatok betöltése során!\n" + e)) : API.Betöltés())
if (list.Contains("orarend"))
API.ÓrarendBetöltés(OpenFileInput("orarend"));
if (list.Contains("osztaly"))
API.OsztályBetöltés(OpenFileInput("osztaly"));
if (list.Contains("helyettesites"))
API.HelyettesítésBetöltés(OpenFileInput("helyettesites"));
var timer = new Timer(CsengőTimer, null, TimeSpan.Zero, new TimeSpan(0, 0, 1));
if (API.Órarendek.Count > 0)
{ {
órarend = API.Órarendek.First(); API.CsengőTimerEvent += CsengőTimer;
órarendfrissítés(); API.Frissítéskor += (_, args) => HelyettesítésFrissítés(false, args);
} }
} }
protected override void OnDestroy()
{
base.OnDestroy();
}
private void AndroidEnvironment_UnhandledExceptionRaiser(object sender, RaiseThrowableEventArgs e)
{
if (!e.Handled) Hiba("Kezeletlen hiba!\n" + e.Exception);
e.Handled = true;
}
private Spinner list;
private void órarendlistafrissítés() private void órarendlistafrissítés()
{ {
handler.Post(() => handler.Post(() =>
{ {
var list = FindViewById<Spinner>(Resource.Id.spinner);
int selected = list.SelectedItemPosition; int selected = list.SelectedItemPosition;
int count = list.Count; int count = list.Count;
ArrayAdapter adapter; ArrayAdapter adapter;
@ -78,78 +84,111 @@ namespace OrarendAndroidApp
private void ÓrarendClick(object sender, AdapterView.ItemSelectedEventArgs e) private void ÓrarendClick(object sender, AdapterView.ItemSelectedEventArgs e)
{ {
órarend = API.Órarendek[e.Position]; API.ÓrarendKiválasztás(e.Position);
órarendfrissítés(); órarendfrissítés();
} }
private void addCell(string text, Color color, TableRow tr1, bool clickable = false, int[] tag = null) [SecuritySafeCritical]
private void addCell(string text, Color color, TableRow tr1, (int, int)? tag = null)
{ {
TextView textview = new TextView(this); TextView textview = new TextView(this);
textview.SetText(text, TextView.BufferType.Normal); textview.SetText(text, TextView.BufferType.Normal);
textview.SetTextColor(color); textview.SetTextColor(color);
textview.SetPadding(10, 10, 10, 10); textview.SetPadding(10, 10, 10, 10);
textview.SetBackgroundResource(Resource.Drawable.cell_shape_light); textview.SetBackgroundResource(DarkTheme ? Resource.Drawable.cell_shape_dark : Resource.Drawable.cell_shape_light);
textview.Tag = tag; textview.Tag = tag.HasValue ? new JavaTuple<int, int>(tag.Value) : null;
if (textview.Clickable = clickable) textview.Clickable = true;
textview.Click += ÓraClick; textview.Click += ÓraClick;
//textview.LongClick += ÓraLongClick;
RegisterForContextMenu(textview);
textview.ContextMenuCreated += ÓraContextMenuCreated;
tr1.AddView(textview); tr1.AddView(textview);
} }
private void HelyettesítésFrissítés() [SecuritySafeCritical]
private class JavaTuple<T1, T2> : Java.Lang.Object
{
public (T1, T2) obj;
public JavaTuple((T1, T2) obj) => this.obj = obj;
public void Deconstruct(out T1 first, out T2 second) => (first, second) = obj;
}
private void HelyettesítésFrissítés(bool internethiba = true, API.FrissítésEventArgs args = null)
{ {
var bar = FindViewById<ProgressBar>(Resource.Id.progressBar1); var bar = FindViewById<ProgressBar>(Resource.Id.progressBar1);
handler.Post(() => bar.Visibility = ViewStates.Visible); //var menu = FindViewById<ActionMenuView>(Resource.Id.actionMenuView1);
API.HelyettesítésFrissítés(OpenFileOutput("helyettesites", FileCreationMode.Private)).ContinueWith(t => Action loadstart = () => bar.Visibility = ViewStates.Visible;
if (internethiba)
handler.Post(loadstart);
else
handler.PostDelayed(loadstart, 500);
API.HelyettesítésFrissítés(() => OpenFileOutput(DATA_FILENAME, FileCreationMode.Private)).ContinueWith(t =>
{ {
handler.RemoveCallbacks(loadstart);
handler.Post(() => handler.Post(() =>
{ {
bar.Visibility = ViewStates.Gone; bar.Visibility = ViewStates.Gone;
Toast.MakeText(this, "Helyettesítések frissítve", ToastLength.Short).Show(); if (TaskHibaNemVolt(t, internethiba) && t.Result)
}); {
});
}
private void ÓrarendFrissítés(Órarend ór = null)
{ //TODO: Meghívni minden tervezett alkalommal; hozzáadásnál csak a hozzáadott órarendet frissítse
var bar = FindViewById<ProgressBar>(Resource.Id.progressBar1);
handler.Post(() => bar.Visibility = ViewStates.Visible);
API.Frissítés(OpenFileOutput("orarend", FileCreationMode.Private), OpenFileOutput("osztaly", FileCreationMode.Private), ór).ContinueWith(t =>
{
handler.Post(() =>
{
if (TaskHiba(t) && (ór == null || ór == órarend))
órarendfrissítés(); órarendfrissítés();
bar.Visibility = ViewStates.Gone; Toast.MakeText(this, "Helyettesítések frissítve", ToastLength.Short).Show();
órarendlistafrissítés(); if (args != null) args.Siker = true;
Toast.MakeText(this, "Órarend" + (ór == null ? "ek" : "") + " és osztálylista frissítve", ToastLength.Short).Show(); }
else if (!internethiba && args != null) args.Siker = true;
}); });
}); });
} }
private void ÓrarendFrissítés(bool auto, Órarend ór = null)
{
var bar = FindViewById<ProgressBar>(Resource.Id.progressBar1);
Action loadstart = () => bar.Visibility = ViewStates.Visible;
if (auto)
handler.PostDelayed(loadstart, 500);
else
handler.Post(loadstart);
API.Frissítés(() => OpenFileOutput(DATA_FILENAME, FileCreationMode.Private), ór).ContinueWith(t =>
{
handler.RemoveCallbacks(loadstart);
handler.Post(() =>
{
bar.Visibility = ViewStates.Gone;
órarendlistafrissítés();
HelyettesítésFrissítés();
if (TaskHibaNemVolt(t))
{
if (ór == null || ór == API.Órarend)
órarendfrissítés();
Toast.MakeText(this, (API.Órarendek.Count > 0 ? "Órarend" + (ór == null ? "ek" : "") + " és o" : "O") + "sztálylista frissítve", ToastLength.Short).Show();
}
});
});
}
private string[] Napok = new string[6] { "Hétfő", "Kedd", "Szerda", "Csütörtök", "Péntek", "Szombat" };
[SecuritySafeCritical]
private void órarendfrissítés() private void órarendfrissítés()
{ {
var table = FindViewById<TableLayout>(Resource.Id.tableLayout1); var table = FindViewById<TableLayout>(Resource.Id.tableLayout1);
if (table.ChildCount > 1) deselect();
table.RemoveViews(1, table.ChildCount - 1); if (table.ChildCount > 0)
FindViewById<TextView>(Resource.Id.kivoraTV).Visibility = ViewStates.Gone; table.RemoveViews(0, table.ChildCount);
if (órarend == null) if (API.Órarend == null)
return; return;
TableRow tr = new TableRow(this); TableRow tr = new TableRow(this);
addCell("", Color.Black, tr); addCell(API.AHét ? "A" : "B", DarkTheme ? Color.White : Color.Black, tr);
addCell("Hétfő", Color.Black, tr); for (int i = 0; i < Napok.Length; i++)
addCell("Kedd", Color.Black, tr); addCell(Napok[i], DarkTheme ? Color.White : Color.Black, tr);
addCell("Szerda", Color.Black, tr);
addCell("Csütörtök", Color.Black, tr);
addCell("Péntek", Color.Black, tr);
addCell("Szombat", Color.Black, tr);
table.AddView(tr, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent)); table.AddView(tr, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent));
byte rowadds = 0;
for (int j = 0; j < 16; j++) for (int j = 0; j < 16; j++)
{ {
tr = new TableRow(this); tr = new TableRow(this);
bool notnull = false; bool notnull = false;
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
{ //Kihagyja az üres sorokat { //Kihagyja az üres sorokat
if (órarend.ÓrákAHét[i][j] != null) if (API.Órarend.Órák[i][j] != null && API.HelyettesítésInnenIde(API.Órarend, i, j).Item2 != null)
{ {
notnull = true; notnull = true;
break; break;
@ -157,44 +196,159 @@ namespace OrarendAndroidApp
} }
if (notnull) if (notnull)
{ {
addCell((j + 1).ToString(), Color.Black, tr); for (int x = 0; x < rowadds; x++)
{
var tr1 = new TableRow(this);
addCell((j + x).ToString(), DarkTheme ? Color.White : Color.Black, tr1);
for (int i = 0; i < 6; i++)
addCell("", Color.Black, tr1);
table.AddView(tr1, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent));
}
rowadds = 0;
addCell((j + 1).ToString(), DarkTheme ? Color.White : Color.Black, tr);
for (int i = 0; i < 6; i++) for (int i = 0; i < 6; i++)
addCell(órarend.ÓrákAHét[i][j] != null ? órarend.ÓrákAHét[i][j].EgyediNév : "", Color.Black, tr, true, new int[2] { i, j }); {
var (innen, ide) = API.HelyettesítésInnenIde(API.Órarend, i, j);
addCell(ide != null ? ide.ÚjÓra.EgyediNév : innen != null ? innen.EredetiNap != innen.ÚjNap || innen.EredetiSorszám != innen.ÚjSorszám ? "áthelyezve" : innen.ÚjÓra?.EgyediNév ?? "elmarad" : API.Órarend.Órák[i][j]?.EgyediNév ?? "", innen == null ? (DarkTheme ? Color.WhiteSmoke : Color.Black) : Color.Red, tr, (i, j));
}
table.AddView(tr, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent)); table.AddView(tr, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WrapContent, ViewGroup.LayoutParams.WrapContent));
} }
else rowadds++;
} }
handler.Post(() => MaiNaphozGörgetés());
}
private (int i, int j, Óra óra, Helyettesítés innen, Helyettesítés ide)? TV2Óra(TextView tv)
{
var ij = (JavaTuple<int, int>)tv.Tag;
int i, j;
Helyettesítés innen, ide;
Óra óra;
if (ij != null)
{
(i, j) = ij;
(innen, ide) = API.HelyettesítésInnenIde(API.Órarend, i, j);
if ((óra = API.Órarend.Órák[i][j]) == null && ide?.ÚjÓra == null)
return null;
}
else
return null;
return (i, j, óra, innen, ide);
}
/// <summary>
/// A cellát nem frissíti, csak a szöveget tünteti el
/// </summary>
private void deselect()
{
FindViewById<TextView>(Resource.Id.kivoraTV).Visibility = ViewStates.Gone;
FindViewById<TextView>(Resource.Id.helyTV).Visibility = ViewStates.Gone;
selected = null;
} }
private TextView selected; private TextView selected;
/// <summary> /// <summary>
/// Kiválasztja az adott órát /// Kiválasztja az adott órát
/// </summary> /// </summary>
[SecuritySafeCritical]
private void ÓraClick(object sender, EventArgs e) private void ÓraClick(object sender, EventArgs e)
{ {
var tv = (TextView)sender; var tv = (TextView)sender;
var ij = (int[])tv.Tag;
Óra óra = órarend.ÓrákAHét[ij[0]][ij[1]];
if (óra == null)
return;
if (selected != null && selected != sender) if (selected != null && selected != sender)
selected.SetBackgroundResource(Resource.Drawable.cell_shape_light); selected.SetBackgroundResource(DarkTheme ? Resource.Drawable.cell_shape_dark : Resource.Drawable.cell_shape_light);
tv.SetBackgroundResource(Resource.Drawable.cell_shape_selected_light); var x = TV2Óra(tv);
if (x == null)
{
deselect();
return;
}
var (i, j, óra, helyettesítésInnen, helyettesítésIde) = x?.ToTuple();
tv.SetBackgroundResource(DarkTheme ? Resource.Drawable.cell_shape_selected_dark : Resource.Drawable.cell_shape_selected_light);
selected = tv; selected = tv;
var kivora = FindViewById<TextView>(Resource.Id.kivoraTV); var kivora = FindViewById<TextView>(Resource.Id.kivoraTV);
kivora.Text = ((TextView)((TableRow)FindViewById<TableLayout>(Resource.Id.tableLayout1).GetChildAt(1)).GetChildAt(ij[0] + 1)).Text + " " + (ij[1] + 1) + ". óra\n" if (óra == null)
+ óra.TeljesNév + "\n" kivora.Visibility = ViewStates.Gone;
+ óra.Terem + "\n" else
+ óra.Tanár.Név + "\n" {
+ órarend.Órakezdetek[ij[1]].ToString("hh\\:mm") + "-" + órarend.Órakezdetek[ij[1]].Add(new TimeSpan(0, 45, 0)).ToString("hh\\:mm") + "\n" kivora.Text = Napok[i] + " " + (j + 1) + ". óra"
+ óra.Csoportok.Aggregate((a, b) => a + ", " + b); + "\nNév: " + óra.TeljesNév
kivora.Visibility = ViewStates.Visible; + "\nTerem: " + óra.Terem
+ "\nTanár: " + óra.Tanár.Név
+ "\nIdőtartam: " + API.Órarend.Órakezdetek[j].ToString("hh\\:mm") + "-" + API.Órarend.Órakezdetek[j].Add(new TimeSpan(0, 45, 0)).ToString("hh\\:mm")
+ "\nCsoport: " + óra.Csoportok.Aggregate((a, b) => a + ", " + b);
kivora.Visibility = ViewStates.Visible;
}
var hely = FindViewById<TextView>(Resource.Id.helyTV);
hely.Text = (helyettesítésInnen == null ? ""
: helyettesítésInnen.EredetiNap != helyettesítésInnen.ÚjNap || helyettesítésInnen.EredetiSorszám != helyettesítésInnen.ÚjSorszám
? "Áthelyezve: innen --> " + Napok[(int)helyettesítésInnen.ÚjNap - 1] + " " + helyettesítésInnen.ÚjSorszám + ". óra"
: helyettesítésInnen.ÚjÓra != null && helyettesítésInnen.ÚjÓra != óra
? "Helyettesítés:"
+ (helyettesítésInnen.ÚjÓra.EgyediNév != óra.EgyediNév ? "\nÓra: " + helyettesítésInnen.ÚjÓra.EgyediNév : "")
+ (helyettesítésInnen.ÚjÓra.Terem != óra.Terem ? "\nTerem: " + helyettesítésInnen.ÚjÓra.Terem : "")
+ (helyettesítésInnen.ÚjÓra.Tanár.Név != óra.Tanár.Név ? "\nTanár: " + helyettesítésInnen.ÚjÓra.Tanár.Név : "")
+ (helyettesítésInnen.ÚjÓra.Csoportok[0] != óra.Csoportok[0] ? "\nCsoport: " + helyettesítésInnen.ÚjÓra.Csoportok.Aggregate((a, b) => a + ", " + b) : "")
: helyettesítésIde != null && (helyettesítésIde.EredetiNap != helyettesítésIde.ÚjNap || helyettesítésIde.EredetiSorszám != helyettesítésIde.ÚjSorszám)
? "" : "Az óra elmarad") //Ha át lett helyezve ide másik óra, akkor nem kell kiírni, hogy elmarad ez az óra
+ (helyettesítésIde == null ? ""
: helyettesítésIde.EredetiNap != helyettesítésIde.ÚjNap || helyettesítésIde.EredetiSorszám != helyettesítésIde.ÚjSorszám
? "Áthelyezve: " + Napok[(int)helyettesítésIde.EredetiNap - 1] + " " + helyettesítésIde.EredetiSorszám + ". óra --> ide"
+ (helyettesítésIde.ÚjÓra.EgyediNév != óra?.EgyediNév ? "\nÓra: " + helyettesítésIde.ÚjÓra.EgyediNév : "")
+ (helyettesítésIde.ÚjÓra.Terem != óra?.Terem ? "\nTerem: " + helyettesítésIde.ÚjÓra.Terem : "")
+ ((óra?.Tanár.Név != (helyettesítésIde.ÚjÓra.Tanár.Név == "" ? API.Órarend.Órák[(int)helyettesítésIde.EredetiNap - 1][helyettesítésIde.EredetiSorszám - 1].Tanár.Név : helyettesítésIde.ÚjÓra.Tanár.Név)) ? "\nTanár: " + (óra?.Tanár.Név == "" ? API.Órarend.Órák[(int)helyettesítésIde.EredetiNap - 1][helyettesítésIde.EredetiSorszám - 1].Tanár.Név : helyettesítésIde.ÚjÓra.Tanár.Név) : "")
+ (helyettesítésIde.ÚjÓra.Csoportok[0] != óra?.Csoportok[0] ? "\nCsoport: " + helyettesítésIde.ÚjÓra.Csoportok.Aggregate((a, b) => a + ", " + b) : "") //ˇˇ De ha változott, akkor nem
: "") //Ha a pozicíó nem változott, a fentebbi rész már kiírta az adatait
;
hely.Visibility = hely.Text.Length > 0 ? ViewStates.Visible : ViewStates.Gone;
}
private void ÓraContextMenuCreated(object sender, View.CreateContextMenuEventArgs e)
{
switch (sender)
{
case TextView tv:
var x = TV2Óra(tv);
Óra óra;
if (x != null)
(_, _, óra, _, _) = x?.ToTuple();
else
óra = null;
if (óra == null)
{ //TODO
ÓraContextItemData.Add(e.Menu.Add("Hozzáadás"), () => StartActivity(new Intent(this, typeof(SettingsActivity))));
}
break;
default:
Hiba("Ismeretlen küldő a menühöz!");
break;
}
}
private Dictionary<IMenuItem, Action> ÓraContextItemData = new Dictionary<IMenuItem, Action>();
private T ctor<T>() where T : new() => new T();
public override bool OnContextItemSelected(IMenuItem item)
{
bool ret = ÓraContextItemData.ContainsKey(item);
if (ret)
ÓraContextItemData[item]();
return ret;
} }
public override bool OnCreateOptionsMenu(IMenu menu) public override bool OnCreateOptionsMenu(IMenu menu)
{ {
MenuInflater.Inflate(Resource.Menu.main_menu_light, menu); MenuInflater.Inflate(Resource.Menu.main_menu_light, menu);
ActionBar.SetCustomView(list = new Spinner(this, SpinnerMode.Dropdown), new ActionBar.LayoutParams(ActionBar.LayoutParams.MatchParent, ActionBar.LayoutParams.MatchParent, GravityFlags.Left));
ActionBar.SetDisplayShowCustomEnabled(true);
if (DarkTheme)
{
menu.FindItem(Resource.Id.menu_add).SetIcon(Resource.Drawable.ic_add_white_24dp);
menu.FindItem(Resource.Id.menu_edit).SetIcon(Resource.Drawable.ic_create_white_24dp);
menu.FindItem(Resource.Id.menu_refresh).SetIcon(Resource.Drawable.ic_autorenew_white_24dp);
menu.FindItem(Resource.Id.menu_preferences).SetIcon(Resource.Drawable.ic_settings_white_24dp);
}
if (API.Osztályok == null || API.Osztályok.Length == 0) if (API.Osztályok == null || API.Osztályok.Length == 0)
ÓrarendFrissítés(); ÓrarendFrissítés(true);
else else
órarendlistafrissítés(); órarendlistafrissítés();
return base.OnCreateOptionsMenu(menu); return base.OnCreateOptionsMenu(menu);
@ -218,50 +372,60 @@ namespace OrarendAndroidApp
} }
case Resource.Id.menu_edit: case Resource.Id.menu_edit:
{ {
if (órarend == null) if (API.Órarend == null)
{ {
Toast.MakeText(this, "Nincs órarend kiválasztva", ToastLength.Short).Show(); Toast.MakeText(this, "Nincs órarend kiválasztva", ToastLength.Short).Show();
break; break;
} }
var intent = new Intent(this, typeof(EditActivity)); var intent = new Intent(this, typeof(EditActivity));
intent.PutExtra("add", false); intent.PutExtra("add", false);
intent.PutExtra("index", API.Órarendek.IndexOf(órarend)); intent.PutExtra("index", API.Órarendek.IndexOf(API.Órarend));
StartActivityForResult(intent, EDIT_ADD_ACT_REQUEST); StartActivityForResult(intent, EDIT_ADD_ACT_REQUEST);
break; break;
} }
case Resource.Id.menu_preferences: //TODO case Resource.Id.menu_preferences:
break; {
var intent = new Intent(this, typeof(SettingsActivity));
StartActivityForResult(intent, SETTINGS_ACT_REQUEST);
break;
}
case Resource.Id.menu_fullrefresh: case Resource.Id.menu_fullrefresh:
{ {
ÓrarendFrissítés(); ÓrarendFrissítés(false);
break; break;
} }
} }
return base.OnOptionsItemSelected(item); return base.OnOptionsItemSelected(item);
} }
private void Hiba(string msg) private void Hiba(string msg) => Hiba(this, msg);
{
Hiba(this, msg);
}
public static void Hiba(Context c, string msg) public static void Hiba(Context c, string msg) =>
{
new AlertDialog.Builder(c).SetMessage(msg).SetNeutralButton("OK", (s, e) => { ((AlertDialog)s).Dismiss(); ((AlertDialog)s).Dispose(); }).SetTitle("Hiba").Show(); new AlertDialog.Builder(c).SetMessage(msg).SetNeutralButton("OK", (s, e) => { ((AlertDialog)s).Dismiss(); ((AlertDialog)s).Dispose(); }).SetTitle("Hiba").Show();
}
/// <summary> /// <summary>
/// Az összes hibát kiírja, ami a <see cref="Task"/> futása közben keletkezett /// Az összes hibát kiírja, ami a <see cref="Task"/> futása közben keletkezett
/// </summary> /// </summary>
/// <param name="t"></param> /// <param name="t"></param>
/// <param name="internethiba">Ha igaz, kiírja a WebException-öket is</param>
/// <returns>Igaz, ha nem volt hiba</returns> /// <returns>Igaz, ha nem volt hiba</returns>
private bool TaskHiba(Task t) private bool TaskHibaNemVolt(Task t, bool internethiba = true)
{ {
bool ret = true; bool ret = true;
foreach (var ex in (IEnumerable<System.Exception>)t.Exception?.InnerExceptions ?? new System.Exception[0]) foreach (var ex in (IEnumerable<Exception>)t.Exception?.InnerExceptions ?? new Exception[0])
{ {
if (ex is WebException) if (ex is WebException wex)
Hiba("Nem sikerült csatlakozni az E-naplóhoz.\n" + ex.Message); {
if (internethiba && wex.Status == WebExceptionStatus.ConnectFailure)
Hiba("Nem sikerült csatlakozni az E-naplóhoz.\nHa van internet, próbáld újraindítani az alkalmazást.");
else if (internethiba)
Hiba("Nem sikerült csatlakozni az E-naplóhoz.\n" + wex.Message);
}
else if (ex is InvalidOperationException oex && oex.Data.Contains("OERROR") && (string)oex.Data["OERROR"] == "CLS_NOT_FOUND")
{
ÓrarendFrissítés(true);
Toast.MakeText(this, oex.Message, ToastLength.Short).Show();
}
else else
Hiba(ex.ToString()); Hiba(ex.ToString());
ret = false; ret = false;
@ -269,82 +433,60 @@ namespace OrarendAndroidApp
return ret; return ret;
} }
private void CsengőTimer(object state) private void CsengőTimer(object sender, TimerEventArgs e)
{ {
handler.Post(() => handler.Post(() =>
{ {
var kezdveg = FindViewById<TextView>(Resource.Id.kezdvegTV); var kezdveg = FindViewById<TextView>(Resource.Id.kezdvegTV);
if (órarend == null)
{
kezdveg.Text = "Nincs órarend kiválasztva";
return;
}
var most = DateTime.Now - DateTime.Today;
bool talált = false;
var kovora = FindViewById<TextView>(Resource.Id.kovoraTV); var kovora = FindViewById<TextView>(Resource.Id.kovoraTV);
if (órarend.Órakezdetek[0] == TimeSpan.Zero) kovora.Visibility = e.KövetkezőÓra == null ? ViewStates.Invisible : ViewStates.Visible;
{ //Még nincsenek beállítva a kezdetek kovora.Text = e.KövetkezőÓra ?? "";
kezdveg.Text = "Betöltés"; kezdveg.Visibility = e.HátralévőIdő == null ? ViewStates.Invisible : ViewStates.Visible;
kovora.Visibility = ViewStates.Invisible; kezdveg.Text = e.HátralévőIdő ?? "";
return;
}
for (int i = 0; i < órarend.Órakezdetek.Length - 1; i++)
{
var vége = órarend.Órakezdetek[i].Add(new TimeSpan(0, 45, 0));
if (most > órarend.Órakezdetek[i])
{
if (most < vége)
{
kezdveg.Text = "Kicsengetés: " + (vége - most).ToString("hh\\:mm\\:ss");
talált = true;
}
else
continue;
}
else
{
kezdveg.Text = "Becsengetés: " + (órarend.Órakezdetek[i] - most).ToString("hh\\:mm\\:ss");
talált = true;
kovora.Visibility = ViewStates.Invisible;
}
int x = (int)DateTime.Today.DayOfWeek - 1;
if (x == -1) //Vasárnap
break;
Óra óra;
if (x < 6 && (óra = órarend.ÓrákAHét[x][i]) != null)
{
kovora.Text = "Következő óra: " + óra.EgyediNév + "\n" + óra.Terem + "\n" + óra.Tanár.Név + "\n" + óra.Csoportok.Aggregate((a, b) => a + ", " + b);
kovora.Visibility = ViewStates.Visible;
}
else
kovora.Visibility = ViewStates.Invisible;
break;
}
if (!talált)
{
kezdveg.Text = "Nincs több óra ma";
kovora.Visibility = ViewStates.Invisible;
}
}); });
} }
protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data) protected override void OnActivityResult(int requestCode, [GeneratedEnum] Result resultCode, Intent data)
{ {
base.OnActivityResult(requestCode, resultCode, data); base.OnActivityResult(requestCode, resultCode, data);
if (resultCode == Result.Canceled)
return;
int index = data.Extras.GetBoolean("add") ? API.Órarendek.Count - 1 : data.Extras.GetInt("index");
if (requestCode == EDIT_ADD_ACT_REQUEST) if (requestCode == EDIT_ADD_ACT_REQUEST)
{ {
if (resultCode == Result.Canceled)
return;
int index = data.Extras.GetBoolean("add") ? API.Órarendek.Count - 1 : data.Extras.GetInt("index");
if (!data.Extras.GetBoolean("deleted")) if (!data.Extras.GetBoolean("deleted"))
ÓrarendFrissítés(API.Órarendek[index]); ÓrarendFrissítés(false, API.Órarendek[index]);
else else
{ {
órarend = null; API.ÓrarendKiválasztásTörlése();
órarendfrissítés(); órarendfrissítés();
} }
órarendlistafrissítés(); órarendlistafrissítés();
} }
else if (requestCode == SETTINGS_ACT_REQUEST)
{
if (data?.Extras?.GetBoolean("offsetchanged") ?? false)
ÓrarendFrissítés(false);
Recreate();
}
}
public override void OnWindowFocusChanged(bool hasFocus)
{
base.OnWindowFocusChanged(hasFocus);
API.Fókusz = hasFocus;
if (!hasFocus)
return;
MaiNaphozGörgetés();
}
private void MaiNaphozGörgetés()
{
var table = FindViewById<TableLayout>(Resource.Id.tableLayout1);
if (table.ChildCount == 0)
return;
var cell = (table.GetChildAt(0) as ViewGroup).GetChildAt((int)API.MaiNap);
FindViewById<HorizontalScrollView>(Resource.Id.horizontalView).SmoothScrollTo(Math.Max(cell.Left - (FindViewById(Resource.Id.container).Width - cell.Width) / 2, 0), 0);
} }
} }
} }

View file

@ -55,15 +55,21 @@
<Reference Include="mscorlib" /> <Reference Include="mscorlib" />
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="System.ValueTuple, Version=4.0.2.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51">
<HintPath>..\packages\System.ValueTuple.4.4.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
</Reference>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="ActivityBase.cs" />
<Compile Include="EditActivity.cs" /> <Compile Include="EditActivity.cs" />
<Compile Include="MainActivity.cs" /> <Compile Include="MainActivity.cs" />
<Compile Include="Resources\Resource.Designer.cs" /> <Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SettingsActivity.cs" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="GettingStarted.Xamarin" /> <None Include="GettingStarted.Xamarin" />
<None Include="packages.config" />
<None Include="Resources\AboutResources.txt" /> <None Include="Resources\AboutResources.txt" />
<None Include="Assets\AboutAssets.txt" /> <None Include="Assets\AboutAssets.txt" />
<AndroidResource Include="Resources\layout\MainLayout.axml"> <AndroidResource Include="Resources\layout\MainLayout.axml">
@ -75,6 +81,7 @@
<AndroidResource Include="Resources\layout\EditLayout.axml"> <AndroidResource Include="Resources\layout\EditLayout.axml">
<SubType>AndroidResource</SubType> <SubType>AndroidResource</SubType>
</AndroidResource> </AndroidResource>
<AndroidResource Include="Resources\menu\ora_menu.axml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AndroidResource Include="Resources\values\Strings.xml" /> <AndroidResource Include="Resources\values\Strings.xml" />
@ -117,15 +124,30 @@
</AndroidResource> </AndroidResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AndroidResource Include="Resources\drawable\cell_shape_removed_light.xml"> <AndroidResource Include="Resources\xml\preferences.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\cell_shape_dark.xml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</AndroidResource> </AndroidResource>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<AndroidResource Include="Resources\drawable\cell_shape_added_light.xml"> <AndroidResource Include="Resources\drawable\cell_shape_selected_dark.xml">
<SubType>Designer</SubType> <SubType>Designer</SubType>
</AndroidResource> </AndroidResource>
</ItemGroup> </ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\ic_add_white_24dp.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\ic_autorenew_white_24dp.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\ic_create_white_24dp.png" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\drawable\ic_settings_white_24dp.png" />
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" /> <Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it. <!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets. Other similar extension points exist, see Microsoft.Common.targets.

View file

@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.github.norbipeti.orarend" android:versionCode="1" android:versionName="1.0" android:installLocation="auto"> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="io.github.norbipeti.orarend" android:versionName="1.2" android:installLocation="auto" android:versionCode="2">
<uses-sdk android:minSdkVersion="14" /> <uses-sdk android:minSdkVersion="11" />
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.INTERNET" />
<application android:label="Orarend"></application> <application android:label="Orarend"></application>
</manifest> </manifest>

View file

@ -45,13 +45,13 @@ namespace OrarendAndroidApp
{ {
// aapt resource value: 0x7f020000 // aapt resource value: 0x7f020000
public const int cell_shape_added_light = 2130837504; public const int cell_shape_dark = 2130837504;
// aapt resource value: 0x7f020001 // aapt resource value: 0x7f020001
public const int cell_shape_light = 2130837505; public const int cell_shape_light = 2130837505;
// aapt resource value: 0x7f020002 // aapt resource value: 0x7f020002
public const int cell_shape_removed_light = 2130837506; public const int cell_shape_selected_dark = 2130837506;
// aapt resource value: 0x7f020003 // aapt resource value: 0x7f020003
public const int cell_shape_selected_light = 2130837507; public const int cell_shape_selected_light = 2130837507;
@ -60,16 +60,28 @@ namespace OrarendAndroidApp
public const int ic_add_black_24dp = 2130837508; public const int ic_add_black_24dp = 2130837508;
// aapt resource value: 0x7f020005 // aapt resource value: 0x7f020005
public const int ic_autorenew_black_24dp = 2130837509; public const int ic_add_white_24dp = 2130837509;
// aapt resource value: 0x7f020006 // aapt resource value: 0x7f020006
public const int ic_create_black_24dp = 2130837510; public const int ic_autorenew_black_24dp = 2130837510;
// aapt resource value: 0x7f020007 // aapt resource value: 0x7f020007
public const int ic_settings_black_24dp = 2130837511; public const int ic_autorenew_white_24dp = 2130837511;
// aapt resource value: 0x7f020008 // aapt resource value: 0x7f020008
public const int Icon = 2130837512; public const int ic_create_black_24dp = 2130837512;
// aapt resource value: 0x7f020009
public const int ic_create_white_24dp = 2130837513;
// aapt resource value: 0x7f02000a
public const int ic_settings_black_24dp = 2130837514;
// aapt resource value: 0x7f02000b
public const int ic_settings_white_24dp = 2130837515;
// aapt resource value: 0x7f02000c
public const int Icon = 2130837516;
static Drawable() static Drawable()
{ {
@ -84,83 +96,83 @@ namespace OrarendAndroidApp
public partial class Id public partial class Id
{ {
// aapt resource value: 0x7f060009 // aapt resource value: 0x7f07000d
public const int ScrollView01 = 2131099657; public const int ScrollView01 = 2131165197;
// aapt resource value: 0x7f06000d // aapt resource value: 0x7f07000a
public const int ScrollView02 = 2131099661; public const int ScrollView02 = 2131165194;
// aapt resource value: 0x7f060013 // aapt resource value: 0x7f070009
public const int actionMenuView1 = 2131099667; public const int container = 2131165193;
// aapt resource value: 0x7f060005 // aapt resource value: 0x7f070005
public const int csoportokEditText = 2131099653; public const int csoportokEditText = 2131165189;
// aapt resource value: 0x7f060008 // aapt resource value: 0x7f070008
public const int deleteButton = 2131099656; public const int deleteButton = 2131165192;
// aapt resource value: 0x7f06000a // aapt resource value: 0x7f070010
public const int horizontalView = 2131099658; public const int helyTV = 2131165200;
// aapt resource value: 0x7f060010 // aapt resource value: 0x7f07000e
public const int kezdvegTV = 2131099664; public const int horizontalView = 2131165198;
// aapt resource value: 0x7f06000f // aapt resource value: 0x7f070012
public const int kivoraTV = 2131099663; public const int kezdvegTV = 2131165202;
// aapt resource value: 0x7f060011 // aapt resource value: 0x7f070011
public const int kovoraTV = 2131099665; public const int kivoraTV = 2131165201;
// aapt resource value: 0x7f060016 // aapt resource value: 0x7f070013
public const int menu_add = 2131099670; public const int kovoraTV = 2131165203;
// aapt resource value: 0x7f060017 // aapt resource value: 0x7f070016
public const int menu_edit = 2131099671; public const int menu_add = 2131165206;
// aapt resource value: 0x7f060019 // aapt resource value: 0x7f070017
public const int menu_fullrefresh = 2131099673; public const int menu_edit = 2131165207;
// aapt resource value: 0x7f060018 // aapt resource value: 0x7f070019
public const int menu_preferences = 2131099672; public const int menu_fullrefresh = 2131165209;
// aapt resource value: 0x7f060015 // aapt resource value: 0x7f070018
public const int menu_refresh = 2131099669; public const int menu_preferences = 2131165208;
// aapt resource value: 0x7f060001 // aapt resource value: 0x7f070015
public const int névEditText = 2131099649; public const int menu_refresh = 2131165205;
// aapt resource value: 0x7f060012 // aapt resource value: 0x7f070001
public const int osztalylistaTV = 2131099666; public const int névEditText = 2131165185;
// aapt resource value: 0x7f060003 // aapt resource value: 0x7f070014
public const int osztálySpinner = 2131099651; public const int osztalylistaTV = 2131165204;
// aapt resource value: 0x7f06000c // aapt resource value: 0x7f070003
public const int progressBar1 = 2131099660; public const int osztálySpinner = 2131165187;
// aapt resource value: 0x7f060007 // aapt resource value: 0x7f07000c
public const int saveButton = 2131099655; public const int progressBar1 = 2131165196;
// aapt resource value: 0x7f06000e // aapt resource value: 0x7f070007
public const int scrollLinearLayout = 2131099662; public const int saveButton = 2131165191;
// aapt resource value: 0x7f060014 // aapt resource value: 0x7f07000b
public const int spinner = 2131099668; public const int scrollLinearLayout = 2131165195;
// aapt resource value: 0x7f06000b // aapt resource value: 0x7f07000f
public const int tableLayout1 = 2131099659; public const int tableLayout1 = 2131165199;
// aapt resource value: 0x7f060000 // aapt resource value: 0x7f070000
public const int textView1 = 2131099648; public const int textView1 = 2131165184;
// aapt resource value: 0x7f060002 // aapt resource value: 0x7f070002
public const int textView2 = 2131099650; public const int textView2 = 2131165186;
// aapt resource value: 0x7f060004 // aapt resource value: 0x7f070004
public const int textView3 = 2131099652; public const int textView3 = 2131165188;
// aapt resource value: 0x7f060006 // aapt resource value: 0x7f070006
public const int textView4 = 2131099654; public const int textView4 = 2131165190;
static Id() static Id()
{ {
@ -197,8 +209,11 @@ namespace OrarendAndroidApp
public partial class Menu public partial class Menu
{ {
// aapt resource value: 0x7f050000 // aapt resource value: 0x7f060000
public const int main_menu_light = 2131034112; public const int main_menu_light = 2131099648;
// aapt resource value: 0x7f060001
public const int ora_menu = 2131099649;
static Menu() static Menu()
{ {
@ -213,11 +228,11 @@ namespace OrarendAndroidApp
public partial class String public partial class String
{ {
// aapt resource value: 0x7f040001 // aapt resource value: 0x7f050001
public const int ApplicationName = 2130968577; public const int ApplicationName = 2131034113;
// aapt resource value: 0x7f040000 // aapt resource value: 0x7f050000
public const int Hello = 2130968576; public const int Hello = 2131034112;
static String() static String()
{ {
@ -228,6 +243,22 @@ namespace OrarendAndroidApp
{ {
} }
} }
public partial class Xml
{
// aapt resource value: 0x7f040000
public const int preferences = 2130968576;
static Xml()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Xml()
{
}
}
} }
} }
#pragma warning restore 1591 #pragma warning restore 1591

View file

@ -2,6 +2,6 @@
<shape <shape
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:shape= "rectangle" > android:shape= "rectangle" >
<solid android:color="#eee"/> <solid android:color="#222"/>
<stroke android:width="1dp" android:color="#00d"/> <stroke android:width="1dp" android:color="#fff"/>
</shape> </shape>

View file

@ -2,6 +2,6 @@
<shape <shape
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:shape= "rectangle" > android:shape= "rectangle" >
<solid android:color="#eee"/> <solid android:color="#333"/>
<stroke android:width="1dp" android:color="#0d0"/> <stroke android:width="1dp" android:color="#fff"/>
</shape> </shape>

Binary file not shown.

After

Width:  |  Height:  |  Size: 127 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 380 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 214 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 460 B

View file

@ -31,7 +31,7 @@
<Spinner <Spinner
android:layout_column="1" android:layout_column="1"
android:id="@+id/osztálySpinner" android:id="@+id/osztálySpinner"
android:layout_width="fill_parent" /> android:layout_width="500dp" />
</TableRow> </TableRow>
<TableRow> <TableRow>
<TextView <TextView

View file

@ -1,42 +1,12 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:orientation="vertical" android:orientation="vertical"
android:layout_width="fill_parent" android:layout_width="fill_parent"
android:layout_height="fill_parent" android:layout_height="fill_parent"
android:minWidth="25px" android:minWidth="25px"
android:minHeight="25px"> android:minHeight="25px">
<ScrollView
android:id="@+id/ScrollView01"
android:layout_height="wrap_content"
android:scrollbars="horizontal"
android:layout_width="match_parent"
android:layout_marginTop="5dip"
android:scrollbarStyle="outsideInset"
android:fillViewport="true">
<HorizontalScrollView
android:id="@+id/horizontalView"
android:layout_height="wrap_content"
android:scrollbars="horizontal"
android:layout_width="wrap_content"
android:layout_marginTop="5dip">
<TableLayout
android:id="@+id/tableLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:stretchColumns="1"
android:isScrollContainer="true">
<ProgressBar
style="@android:attr/progressBarStyleHorizontal"
android:id="@+id/progressBar1"
android:indeterminateTint="#00ffffff"
android:indeterminate="true"
android:indeterminateBehavior="repeat"
android:indeterminateOnly="true"
android:indeterminateTintMode="add"
android:visibility="gone" />
</TableLayout>
</HorizontalScrollView>
</ScrollView>
<ScrollView <ScrollView
android:id="@+id/ScrollView02" android:id="@+id/ScrollView02"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -52,6 +22,48 @@
android:minWidth="25px" android:minWidth="25px"
android:minHeight="25px" android:minHeight="25px"
android:id="@+id/scrollLinearLayout"> android:id="@+id/scrollLinearLayout">
<ProgressBar
style="@android:attr/progressBarStyleHorizontal"
android:id="@+id/progressBar1"
android:indeterminateTint="#00ffffff"
android:indeterminate="true"
android:indeterminateBehavior="repeat"
android:indeterminateOnly="true"
android:indeterminateTintMode="add"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:visibility="gone" />
<ScrollView
android:id="@+id/ScrollView01"
android:layout_height="wrap_content"
android:scrollbars="horizontal"
android:layout_width="match_parent"
android:layout_marginTop="5dip"
android:scrollbarStyle="outsideInset"
android:fillViewport="true">
<HorizontalScrollView
android:id="@+id/horizontalView"
android:layout_height="wrap_content"
android:scrollbars="horizontal"
android:layout_width="wrap_content"
android:layout_marginTop="5dip">
<TableLayout
android:id="@+id/tableLayout1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:stretchColumns="1"
android:isScrollContainer="true" />
</HorizontalScrollView>
</ScrollView>
<TextView
android:id="@+id/helyTV"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Helyettesítés"
android:textSize="14sp"
android:textStyle="bold"
android:visibility="gone"
android:textColor="#FF0000" />
<TextView <TextView
android:id="@+id/kivoraTV" android:id="@+id/kivoraTV"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -85,10 +97,4 @@
android:visibility="gone" /> android:visibility="gone" />
</LinearLayout> </LinearLayout>
</ScrollView> </ScrollView>
<ActionMenuView
android:minWidth="25px"
android:minHeight="25px"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/actionMenuView1" />
</LinearLayout> </LinearLayout>

View file

@ -1,9 +1,10 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8" ?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android">
<item android:id="@+id/spinner" <!-- <item android:id="@+id/spinner"
android:title="will be replaced anyway" android:title="will be replaced anyway"
android:showAsAction="always" android:showAsAction="always"
android:actionViewClass="android.widget.Spinner" /> android:actionViewClass="android.widget.Spinner"
android:layout_width="fill_parent" /> -->
<item <item
android:id="@+id/menu_refresh" android:id="@+id/menu_refresh"
android:icon="@drawable/ic_autorenew_black_24dp" android:icon="@drawable/ic_autorenew_black_24dp"

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8" ?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_refresh"
android:title="Frissítés" />
<item
android:id="@+id/menu_add"
android:title="Hozzáadás" />
<item
android:id="@+id/menu_edit"
android:title="Szerkesztés" />
<item
android:id="@+id/menu_preferences"
android:title="Beállítások" />
<item
android:id="@+id/menu_fullrefresh"
android:title="Órarendfrissítés" />
</menu>

View file

@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<CheckBoxPreference
android:key="pref_theme"
android:title="Sötét téma"
android:summary="Sötét téma"
android:defaultValue="false" />
<Preference
android:key="pref_commonnames"
android:title="Gyakori óranevek"
android:summary="Gyakori óranevek használata" />
<EditTextPreference
android:key="pref_offset"
android:title="Óra eltolás"
android:summary="Pl. ha 1, akkor az első óra 8:15-kor kezdődik."
android:defaultValue="0"
android:numeric="integer" />
</PreferenceScreen>

View file

@ -0,0 +1,86 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Preferences;
using Orarend;
using System.Security;
namespace OrarendAndroidApp
{
[Activity(Label = "Beállítások", Theme = "@android:style/Theme.Holo.Light")]
public class SettingsActivity : PreferenceActivity, ISharedPreferencesOnSharedPreferenceChangeListener, Preference.IOnPreferenceClickListener
{
protected override void OnCreate(Bundle savedInstanceState)
{
ActivityBase.SetTheme(this);
/*var settings = PreferenceManager.GetDefaultSharedPreferences(this);
bool darktheme = settings.GetBoolean("pref_theme", false);
//SetTheme(darktheme ? Android.Resource.Style.ThemeDeviceDefault : Android.Resource.Style.ThemeDeviceDefaultLight);
SetTheme(darktheme ? Android.Resource.Style.ThemeHolo : Android.Resource.Style.ThemeHoloLight);*/
base.OnCreate(savedInstanceState);
#pragma warning disable CS0618 // Type or member is obsolete
AddPreferencesFromResource(Resource.Xml.preferences);
FindPreference("pref_commonnames").OnPreferenceClickListener = this;
#pragma warning restore CS0618 // Type or member is obsolete
PreferenceManager.SetDefaultValues(this, Resource.Xml.preferences, false);
}
private Intent intent;
public void OnSharedPreferenceChanged(ISharedPreferences sharedPreferences, string key)
{
switch (key)
{
case "pref_theme":
Recreate();
break;
case "pref_commonnames":
API.Beállítások.UseCommonNames();
Toast.MakeText(this, "Óranevek frissítve", ToastLength.Short).Show();
break;
case "pref_offset":
API.Beállítások.ÓraOffset = sbyte.Parse(sharedPreferences.GetString(key, "0"));
intent = new Intent(Intent);
intent.PutExtra("offsetchanged", true);
SetResult(Result.Ok, intent);
break;
}
}
protected override void OnResume()
{
base.OnResume();
PreferenceManager.GetDefaultSharedPreferences(this).RegisterOnSharedPreferenceChangeListener(this);
}
protected override void OnPause()
{
base.OnPause();
PreferenceManager.GetDefaultSharedPreferences(this).UnregisterOnSharedPreferenceChangeListener(this);
}
public override void OnBackPressed()
{
SetResult(Result.Ok, intent);
//base.OnBackPressed();
Finish();
}
public bool OnPreferenceClick(Preference preference)
{
if (preference.Key == "pref_commonnames")
{
API.Beállítások.UseCommonNames();
Toast.MakeText(this, "Óranevek frissítve", ToastLength.Short).Show();
}
return true;
}
}
}

View file

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="System.ValueTuple" version="4.4.0" targetFramework="monoandroid60" />
</packages>

6
README.md Normal file
View file

@ -0,0 +1,6 @@
# Orarend
A school schedule app written in C# using Xamarin.
This app can obtain the schedule automatically from the school's website and update it as needed. Any temporary changes are marked red.
It downloads the site HTML and uses regex to fix some issues that the parser can't handle correctly and then parses the code.