/feedtree.hws (a1ac5af9c9ebafc5b2a012753079ee9602fbb98f) (8773 bytes) (mode 100755) (type blob)


Const #LIST_TREE = "feedtree"

Const #FEED_STATUS_NEW = 5
Const #FEED_STATUS_READ = 4

Const #FEED_STATUS_SUCCESS = 1

Const #FEED_STATUS_INTERRUPTED = -2
Const #FEED_STATUS_ERROR = -3


Function p_FillListTree(listtree$, treetable)
	mui.Set(listtree$, "Quiet", True)
	;č ForEach začíná od 1 a teprve na konci se vrací k 0
	;ForEach(treetable, p_InsertNode, listtree$)

	For _i, t In IPairs(treetable)
    	mui.DoMethod(listtree$, "Insert",
			t.name, t.id, t.parent, "Tail", IIf(t.isNode, "List", ""))
		;č pro jednotlivé položky nelze zadat kontextové menu  
		;mui.Set(t.id, "ContextMenu", "channeltitlemenu")
    Next
	mui.Set(listtree$, "Quiet", False)
EndFunction


Function p_DumpFeedTree()
	cFeeds = CreateList() ;currentFeeds
	p_DumpListTree(#LIST_TREE, cFeeds, "Root", "Root")
	Return(cFeeds)
EndFunction
        

;č tohle musí být rekurzivní 
Function p_DumpListTree(listtree$, tabletree, nodeid, muiid)
	Local isFound, t = mui.DoMethod(listtree$, "GetEntry", muiid, "Head", "")
	While isFound ;And HaveItem(t, "id")
		;č tady je možná chyba, kterou nemá cenu hlídat.
		;č pokud uživatel docílí toho, že strom vrátí prvek bez id,
		;č tak hlídej-nehlídej - program je odsouzen k meditaci
		InsertItem(tabletree, {id=t.id, name=t.name, isNode=t.node, parent=nodeid})
		If t.Node = True Then p_DumpListTree(listtree$, tabletree, t.id, t.muiid)
		isFound, t = mui.DoMethod(listtree$, "GetEntry", t.muiid, "Next", "")
	Wend
EndFunction
        



Function p_FetchAll()
	p_Lock() 
	If IsOnline() Then  p_FetchGroup("Root")
	p_Unlock()
EndFunction

;č zjistit co je Node zač, 
;č podle toho postupovat
Function p_FetchCurrent()
	p_Lock() 
	Local isFound, t = mui.DoMethod(#LIST_TREE, "GetEntry", "Active", "Active", "")
	If isFound And Not PleaseStop And IsOnline()
		If t.Node 
			p_FetchGroup(t.muiid)
		Else
			Local status = p_Fetch(t.id)
			If status = #FEED_STATUS_NEW
				p_MarkFeed(t.id, #FEED_STATUS_READ)
				Ivor:Load(t.id) 
			ElseIf status = #FEED_STATUS_SUCCESS
				p_MarkFeed(t.id, #FEED_STATUS_READ)
			Else
				p_MarkFeed(t.id, status)
			EndIf 
		EndIf 
	EndIf 
	p_Unlock()
EndFunction


Function p_ShowCurrent()
	Local isFound, t = mui.DoMethod(#LIST_TREE, "GetEntry", "Active", "Active", "")
	If Not isFound Or t.Node Then Return()
		 
	If HaveItem(feedsdata, t.id)
		If fd_Get(t.id, "status") = #FEED_STATUS_NEW
			p_MarkFeed(t.id, #FEED_STATUS_READ)
		EndIf 
		Ivor:Load(t.id) 
	Else
		Ivor:Clear()
	EndIf
EndFunction

;č zjistit co je Node zač, 
;č podle toho postupovat
;č musí být rekurzivní
Function p_FetchGroup(muiid$)
	Local isFound, t = mui.DoMethod(#LIST_TREE, "GetEntry", muiid$, "Head", "")
	While isFound And Not PleaseStop
		If t.Node 
			p_FetchGroup(t.muiid)
		Else
			p_FetchFeed(t.id)
		EndIf 
		isFound, t = mui.DoMethod(#LIST_TREE, "GetEntry", t.muiid, "Next", "")
	Wend
EndFunction


;č označit buď jako nové, nebo jako přečtené
;č smí se posílat JENOM fidy, nikoliv skupiny 
Function p_FetchFeed(feedid$)
	Local status = p_Fetch(feedid$)
	If status = #FEED_STATUS_SUCCESS
		If fd_Get(feedid$, "status") = #FEED_STATUS_NEW Then Return()
		status = #FEED_STATUS_READ
	EndIf 
	p_MarkFeed(feedid$, status)
EndFunction



Function p_MarkFeed(feedid$, status)
	;č ekonomie na nesprávném místě
	;If fd_isEqualOrSet(feedid$, "status", status) Then Return()
	fd_Set(feedid$, "status", status)
	
	Local preparse$ = ""
	Switch status
	Case #FEED_STATUS_NEW:
		preparse$ = "\27".."5\27b"
	Case #FEED_STATUS_READ:
		preparse$ = "\27".."5"
	Case #FEED_STATUS_INTERRUPTED:
		preparse$ = "\27".."5\27i"
	Case #FEED_STATUS_ERROR:
		preparse$ = "\27i"
	EndSwitch
	
	mui.DoMethod(#LIST_TREE, "Rename", feedid$, preparse$ .. feedid$)
EndFunction






Function p_RemoveCurrent()
	Local isFound, t = mui.DoMethod(#LIST_TREE, "GetEntry", "Active", "Active", "")
	If isFound And mui.Request("Delete ".. IIf(t.Node, "group", "RSS feed"),
					"Do you realy want to delete ".. t.Name .. 
					IIf(t.Node, " \27ngroup and all its content?", "\27n?"), 
					"Yes|*Cancel", "Warning") 
		mui.DoMethod(#LIST_TREE, "Remove", "Active", t.id)
		;č vyhodit i přidružená data.   
		;č Hollywood se pak doopravdy tváří, že tu položku nikdy neznal,
		;č HaveItem vrací lež no a přístup pak způsobí chybu		
		feedsdata[LowerStr(t.id)] = nil
		;č Na soubory ve složce Feeds sereme?
	EndIf 
	p_SaveFeeds() 
EndFunction


Function p_CreateGroup()
	Local s$, ok = StringRequest("Create Group", "Enter new group name")
	
	If EmptyStr(s$) Then Return()
	s$ = StripStr(s$)
	If p_HasItem(s$, "Root")
		mui.Set("status", "Contents", "\27bGroup "..s$ .. " already exists")
	Else
		mui.DoMethod(#LIST_TREE, "Insert", "\27b"..s$, s$, "Root", 
					IIf(mui.Get(#LIST_TREE, "Active")="Off", "Tail","Active"),
					"List; Active")
		p_SaveFeeds() 
		;p_Replay(err_code, "Group ".."\27b"..s$ .. " has been created") 
	EndIf
	
EndFunction


Function p_AddFeedRequest()
	Local type, data$ = GetClipboard()
	Local s$, ok = StringRequest("Add RSS feed", "Enter feed adress", 
					IIf(type = #CLIPBOARD_TEXT And StartsWith(data$, "http"), 
															{Text=data$}, {}))
	p_AddFeed(s$)
	p_SaveFeeds() 
EndFunction


Function p_AddFeed(feedid$)
	If EmptyStr(feedid$) Then Return()
	feedid$ = StripStr(feedid$)
	If p_HasItem(feedid$, "Root")
		mui.Set("status", "Contents", feedid$ .. " \27balready exists")
	Else
		mui.DoMethod(#LIST_TREE, "Insert", feedid$, feedid$, "Root", 
					IIf(mui.Get(#LIST_TREE, "Active")="Off", "Tail","Active"),
					"Active")
	EndIf
EndFunction


;č Kurňadrát, RapaGUI takové starosti nemá...
;č jen pro zábavu 
Function p_CanHas(nodeid$)
	Return(Not p_HasItem(nodeid$, "Root"))
EndFunction       

;č tohle musí být rekurzivní 
Function p_HasItem(nodeid$, muiid)
	Local isFound, t = mui.DoMethod(#LIST_TREE, "GetEntry", muiid, "Head", "")
	While isFound
		;InsertItem(tabletree, {id=t.id, name=t.name, isNode=t.node, parent=nodeid})
		If LowerStr(t.id) = LowerStr(nodeid$) Then Return(True)
		If t.Node And p_HasItem(nodeid$, t.muiid) Then Return(True)
		isFound, t = mui.DoMethod(#LIST_TREE, "GetEntry", t.muiid, "Next", "")
	Wend
	Return(False)
EndFunction

Function p_SaveFeeds() 
	Local err_code = ?StringToFile(SerializeTable(
							p_DumpFeedTree()), "feeds.json")
	p_Replay(err_code, "Feeds saved") 
EndFunction 	





Function p_HideFeeds() 
	mui.DoMethod(#LIST_TREE, "close", "root", "all")
EndFunction 

Function p_ExpandFeeds() 
	mui.DoMethod(#LIST_TREE, "open", "root", "all")
EndFunction 












;č stáhnout soubor
;č možné statusy
/* 
#FEED_STATUS_NEW  
#FEED_STATUS_SUCCESS
#FEED_STATUS_INTERRUPTED
#FEED_STATUS_ERROR
*/
Function p_Fetch(url$)
	;č zjednodušená kontrola, pokud řetězec obsahuje procenta,
	;č považujeme ho za "eskejpnutý".
	;č Na případ, kdy uživatel strčí do URLu osamělý znak procenta vysereme 
	Local err_code, xml$, count = ?DownloadFile(url$, 
			{Adapter="hurl", Fail404=True, Encoded=FindStr(url$, "%", True) <> -1},
			p_callback, url$)
	p_Replay(err_code, count .. "bytes from " .. url$ .. " transmitted")
	CheckEvents() ; keep MUI even more responsive
	If err_code <> #ERR_NONE Then Return(#FEED_STATUS_ERROR)	

	If PleaseStop Then Return(#FEED_STATUS_INTERRUPTED)
	
	If fd_isEqualOrSet(url$, "checksum", CRC32Str(xml$)) 
		Return(#FEED_STATUS_SUCCESS)
	EndIf 
	
	Local err_code = ?StringToFile(xml$, p_GetXMLname(url$))
	p_Replay(err_code, "Updated XML file saved")
	If err_code = #ERR_NONE 
		;č kolikrát weby dodají do RSS nějaký BuildDate, 
		;č kterým se RSS formálně změní. 
		;č Takže zde, na místě, když ještě máme xml v ruce, 
		;č musíme rozhodnout, zda je v tom RSS doopravdy něco nového.
		;č Půjdeme podle guid. Když se změní, tak asi kvůli novému článku.
		;č Kódování nemusíme řešit, je to jen pro nás, 
		;č žádný parser zde volat nebudeme.  
		Local guidpos = FindStr(xml$, "<guid", False, 0, #ENCODING_RAW)
		Local guidsum = 0
		If guidpos > 0
			Local guidend = FindStr(xml$, "</guid", False, guidpos, #ENCODING_RAW)
			Local len = guidend - guidpos
			If len > 0
				guidsum = CRC32Str(MidStr(xml$, guidpos, len, #ENCODING_RAW))
			EndIf				
		EndIf 
		
		If fd_isEqualOrSet(url$, "guidsum", guidsum) 
			Return(#FEED_STATUS_SUCCESS)
		EndIf 
		
		p_Replay(err_code, "\27".."5\27b" .. url$ .. " Updated!")
		Return(#FEED_STATUS_NEW)
	Else
		;č Aha... Tak zpětně vynulujeme čeksumu, aby příště zkusil to uložit znovu 
		fd_Set(url$, "checksum", False)
		Return(#FEED_STATUS_ERROR)
	EndIf		
EndFunction


Function p_CopyTreeURL()
	Local isFound, t = mui.DoMethod(#LIST_TREE, "GetEntry", "Active", "Active", "")
	If isFound
		err_code = ?SetClipboard(#CLIPBOARD_TEXT, t.id)
		p_Replay(err_code, "Copied!")
	EndIf 
EndFunction

Mode Type Size Ref File
100755 blob 7473 1ab45355102d3c454b8d83e05e4af10b0447dee3 128px-Feed-icon.png
100755 blob 5559 b4b21e48b891dd64eb9d1bc4a2897ce50bb139ac AppWindow.xml
100755 blob 4295 56bbaba364cbffee6db0569e7c727b45ec3a7355 IvoR.hws
100755 blob 8539 5fb3546290c06f2b7077fbedb85cef583a60e574 IvoRSS.hws
100755 blob 7191 6291191cf3b1e9b7dd44493a09e26918f2c6e3d1 IvoRSS.png
100755 blob 4405 6f1fc460afb31e6e38cd78dd01c0debaae6f5343 feeds.hws
100755 blob 1694 83e47eb86860331dfe771f49029c00559a2f687e feedsdata.hws
100755 blob 8773 a1ac5af9c9ebafc5b2a012753079ee9602fbb98f feedtree.hws
100755 blob 6412 f39265cc944ed3be89260bc28f32c3805794fb0d lurk.hws
Hints:
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://rocketgit.com/user/iam-git/IvoRSS

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@ssh.rocketgit.com/user/iam-git/IvoRSS

Clone this repository using git:
git clone git://git.rocketgit.com/user/iam-git/IvoRSS

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a merge request:
... clone the repository ...
... make some changes and some commits ...
git push origin main