Page Menu
Home
Musing Studio
Search
Configure Global Search
Log In
Files
F12338329
PostListModel.swift
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Award Token
Flag For Later
Size
4 KB
Subscribers
None
PostListModel.swift
View Options
import
SwiftUI
import
CoreData
class
PostListModel
:
ObservableObject
{
func
remove
(
_
post
:
WFAPost
)
{
withAnimation
{
LocalStorageManager
.
persistentContainer
.
viewContext
.
delete
(
post
)
LocalStorageManager
().
saveContext
()
}
}
func
purgePublishedPosts
()
{
let
fetchRequest
:
NSFetchRequest
<
NSFetchRequestResult
>
=
NSFetchRequest
(
entityName
:
"WFAPost"
)
fetchRequest
.
predicate
=
NSPredicate
(
format
:
"status != %i"
,
0
)
let
deleteRequest
=
NSBatchDeleteRequest
(
fetchRequest
:
fetchRequest
)
do
{
try
LocalStorageManager
.
persistentContainer
.
viewContext
.
executeAndMergeChanges
(
using
:
deleteRequest
)
}
catch
{
print
(
"Error: Failed to purge cached posts."
)
}
}
func
getBodyPreview
(
of
post
:
WFAPost
)
->
String
{
var
elidedPostBody
:
String
=
""
// Strip any markdown from the post body.
let
strippedPostBody
=
stripMarkdown
(
from
:
post
.
body
)
// Extract lede from post.
elidedPostBody
=
extractLede
(
from
:
strippedPostBody
)
return
elidedPostBody
}
}
private
extension
PostListModel
{
func
stripMarkdown
(
from
string
:
String
)
->
String
{
var
strippedString
=
string
strippedString
=
stripHeadingOctothorpes
(
from
:
strippedString
)
strippedString
=
stripImages
(
from
:
strippedString
,
keepAltText
:
true
)
return
strippedString
}
func
stripHeadingOctothorpes
(
from
string
:
String
)
->
String
{
let
newLines
=
CharacterSet
.
newlines
var
processedComponents
:
[
String
]
=
[]
let
components
=
string
.
components
(
separatedBy
:
newLines
)
for
component
in
components
{
if
component
.
isEmpty
{
continue
}
var
newString
=
component
while
newString
.
first
==
"#"
{
newString
.
removeFirst
()
}
if
newString
.
hasPrefix
(
" "
)
{
newString
.
removeFirst
()
}
processedComponents
.
append
(
newString
)
}
let
headinglessString
=
processedComponents
.
joined
(
separator
:
"
\n\n
"
)
return
headinglessString
}
func
stripImages
(
from
string
:
String
,
keepAltText
:
Bool
=
false
)
->
String
{
let
pattern
=
#
"!\[[
\"
]?(.*?)[
\"
|]?\]
\(
.
*?
\
)
"
#
var
processedComponents
:
[
String
]
=
[]
let
components
=
string
.
components
(
separatedBy
:
.
newlines
)
for
component
in
components
{
if
component
.
isEmpty
{
continue
}
var
processedString
:
String
=
component
if
keepAltText
{
let
regex
=
try
?
NSRegularExpression
(
pattern
:
pattern
,
options
:
[])
if
let
matches
=
regex
?.
matches
(
in
:
component
,
options
:
[],
range
:
NSRange
(
location
:
0
,
length
:
component
.
utf16
.
count
)
)
{
for
match
in
matches
{
if
let
range
=
Range
(
match
.
range
(
at
:
1
),
in
:
component
)
{
processedString
=
"
\(
component
[
range
]
)
"
}
}
}
}
else
{
let
range
=
component
.
startIndex
..<
component
.
endIndex
processedString
=
component
.
replacingOccurrences
(
of
:
pattern
,
with
:
""
,
options
:
.
regularExpression
,
range
:
range
)
}
if
processedString
.
isEmpty
{
continue
}
processedComponents
.
append
(
processedString
)
}
return
processedComponents
.
joined
(
separator
:
"
\n\n
"
)
}
func
extractLede
(
from
string
:
String
)
->
String
{
let
truncatedString
=
string
.
prefix
(
80
)
let
terminatingPunctuation
=
".。?"
let
terminatingCharacters
=
CharacterSet
(
charactersIn
:
terminatingPunctuation
).
union
(.
newlines
)
var
lede
:
String
=
""
let
sentences
=
truncatedString
.
components
(
separatedBy
:
terminatingCharacters
)
if
let
firstSentence
=
(
sentences
.
filter
{
!
$0
.
isEmpty
}).
first
{
if
truncatedString
.
count
>
firstSentence
.
count
{
if
terminatingPunctuation
.
contains
(
truncatedString
[
firstSentence
.
endIndex
])
{
lede
=
String
(
truncatedString
[...
firstSentence
.
endIndex
])
}
else
{
lede
=
firstSentence
}
}
else
if
truncatedString
.
count
==
firstSentence
.
count
{
if
string
.
count
>
80
{
if
let
endOfStringIndex
=
truncatedString
.
lastIndex
(
of
:
" "
)
{
lede
=
truncatedString
[..<
endOfStringIndex
]
+
"…"
}
}
else
{
lede
=
firstSentence
}
}
}
return
lede
}
}
File Metadata
Details
Attached
Mime Type
text/x-c++
Expires
Sat, Nov 15, 8:15 AM (8 h, 15 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3491793
Attached To
rWFSUI WriteFreely SwiftUI
Event Timeline
Log In to Comment